Making a SN site I've tried this module and found some mistakes (d 6.3)

1) include in realname_init() is never used because theme('username' is always goes to theme_username (phptemplate never examined) so I comment it out

2) in realname_make_name better include a caching,
$account->{$fields[0]['name']} is wrong and bring warning because profile field name not always is "name" so I place this checking into loop with condition to work only once
Finally it looks:

function realname_make_name(&$account) {
  static $users = array();
  if (isset($users[$account->uid])) {
    return $users[$account->uid];
  }

  $fields = variable_get('realname_fields', array());
  $pattern = variable_get('realname_pattern', ' ');

  // Has the profile been loaded?
  //if (!isset($account->{$fields[0]['name']})) {
    //profile_load_profile($account);
  //}

  $stuff = array();
  $i = 0;
  foreach ($fields as $name => $weight) {
    // Has the profile been loaded?
    if (!isset($account->$name) && $i == 0) {
      profile_load_profile($account);
    }
    ++$i;
    if (isset($account->$name)) {
      $stuff['%'. $i] = check_plain($account->$name);
    }
    else {
      // If there is no value, remove the patterm piece, except the first.
      $pattern = $i > 1 ? str_replace('%'. $i, null, $pattern) : $pattern;
    }
  }

  // If no fields set, use username.
  if (count($stuff) == 0) {
    $stuff['%1'] = $account->name;
  }

  // TODO: Make a pattern, rather than hard separator.
  $string = trim(strtr($pattern, $stuff));
  //Store in static cache
  $users[$account->uid] = $string;
  return $string;
}

2) Little optimization in hook_user if user already get realname so no need to realname_make...

function realname_user($op, &$edit, &$account, $category = null) {
  if ($op == 'load') {
    if (!isset($account->realname)) {
      $account->realname = realname_make_name($account);
    }
    //if theme then replace name with realname
    //hard-coded fix for theming which work only for theme('username' that call user_load
    if (variable_get('realname_theme', false)) {
      //Store it for places where it needed
      $account->realname_save = $account->name;
      $account->name = $account->realname;
    }
  }
}

Proposals:
- put code from realname_theme.inc to yourthemename_username function in template.php
- avoid $account = user_load(array('uid' => $object->uid)); in theme - it brings a high load on DB if a lot of username on page
- better to use $account->realname in templates and never set 'realname_theme' checkbox!

CommentFileSizeAuthor
#9 realname.txt759 bytesandypost
#9 realname2.txt685 bytesandypost
#7 realname.module.patch1.49 KBComputerWolf

Comments

wojtha’s picture

Hi, I've also find the $account->{$fields[0]['name']} bug, but I've thinked out much simpler fix. Only change the line 133 to this: if (!isset($account->{key($fields)}))

There is no need to have the $user as a static variable actually for this reason. I think when we store realname in the $account object, we don't need to store realname in the static array $user[uid]. I will make a try what and how exactly Drupal caches accounts. When Drupal load one node (& user author account w/ profile) and then use the account in other case (i.e. second node). If the Drupal loads the user profile twice, it will be the reason for static caching :-)

function realname_make_name(&$account) {
  $fields = variable_get('realname_fields', array());
  $pattern = variable_get('realname_pattern', ' ');

  // Has the profile been loaded?
  //if (!isset($account->{$fields[0]['name']})) {
  // ^^ this produced lots of notices (15 actually on the page mysite.com/user/1)
  // notice: Undefined offset: 0 in D:\workspace\...\realname.module on line 133.
  // error_reporting(E_ALL); ini_set('display_errors', 'On'); This is very usefull for bug catching ...
  if (!isset($account->{key($fields)})) {
    profile_load_profile($account);
  }

   ... etc

wojtha’s picture

andypost your patch causes one unwanted thing. The line "$account->name = $account->realname;" in hook_user causes that username on user edit form (user/%/edit) is now realname.

If we want to keep this feature, we need to fix the form in the hook_form_alter. This hook is already implemented so we only add one "case" ~ three lines of code.

/**
 * Implementation of hook_form_alter().
 * Intercepts the contact forms to show the realname.
 */
function realname_form_alter(&$form, $form_state, $form_id) {
  global $user;
  
  switch ($form_id) {
    // FIX for $account->name
    case 'user_profile_form':
      $form['account']['name']['#default_value'] = $form['_account']['#value']->realname_save;
      break;
    case 'contact_mail_user':

   ... etc

ComputerWolf’s picture

If you indeed apply the fix for $account->name, you will need to make sure that $account->realname_save actually contains the correct data. The following code prevents $account->realname_save from using an already modified $account->realname in hook_user.

<?php
if (!isset($account->realname_save))
      {
      $account->realname_save = $account->name;
      $account->name = $account->realname;
      }
?>
ComputerWolf’s picture

Correction: that code causes errors pertaining to the objects when someone attempts to sign up. This code fixes that issue, at least in all my tests.

<?php
if (!isset($account->realname_save) && is_object($account))
      {
      $account->realname_save = $account->name;
      $account->name = $account->realname;
      }
?>
nancydru’s picture

Can one of you roll an actual patch, please? There are instructions on the project page on how to become a co-maintainer.

lomz’s picture

A patch would be great.

ComputerWolf’s picture

Status: Needs work » Needs review
StatusFileSize
new1.49 KB

Here's the patch for what I believe are all the changes. Works as it should on my own site.

nancydru’s picture

Status: Needs review » Fixed

Committed on both branches.

andypost’s picture

Version: 6.x-1.0-beta » 6.x-1.x-dev
Status: Fixed » Needs work
StatusFileSize
new685 bytes
new759 bytes

Patch with static caching.
Using user_load is very expensive! Try devel and compare queries better for pages with a lot of "usernames"
Second patch (_theme) disable user_load in theming

nancydru’s picture

Status: Needs work » Needs review

Thanks. Hopefully I can do this before the end of the weekend. I have places to go right now.

nancydru’s picture

Status: Needs review » Fixed

Committed to both branches.

nancydru’s picture

Status: Fixed » Closed (fixed)
TripleEmcoder’s picture

Status: Closed (fixed) » Active

I am reactivating this because the realname_save workaround is causing some side-effects in other modules.

This is realname code:

case 'user_profile_form':
      if (variable_get('realname_theme', TRUE)) {
        $form['account']['name']['#default_value'] = $form['_account']['#value']->realname_save;
      }
      break;

However according to http://api.drupal.org/api/function/user_edit_form/6 this is how Core prepares the field:

if ($register || ($GLOBALS['user']->uid == $uid && user_access('change own username')) || $admin) {
    $form['account']['name'] = array('#type' => 'textfield',
      '#title' => t('Username'),
      '#default_value' => $edit['name'],
      '#maxlength' => USERNAME_MAX_LENGTH,
      '#description' => t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, and underscores.'),
      '#required' => TRUE,
    );
  }

Notice that if the user does not have permissions to change own username then the field is not present in $form at all. Now code in RealName doesn't check permissions or the field's existance and create such entries:

    ["name"]=>
    array(1) {
      ["#default_value"]=>
      string(18) "memfis"
    }

When other modules test for name field existance like RealName should, they are fooled by this and start some processing which leads to unexpected results. This happens with the UserProtect module.

I would suggest to change RealName code this way (added check for name field):

    case 'user_profile_form':
      if (variable_get('realname_theme', TRUE) && isset($form['account']['name'])) {
        $form['account']['name']['#default_value'] = $form['_account']['#value']->realname_save;
      }
      break;

This solves the issue with UserProtect and potentially other modules.

hass’s picture

Status: Active » Closed (outdated)