4

I'm trying to display roles in the default user profile (no profile2) with consistent formatting to the other fields being displayed.

In user-profile.tpl.php I have this:

<div class="profile"<?php print $attributes; ?>>
    <?php
    // var_dump($user_profile); exit;
    $account = user_load(arg(1));
    $roles = '';
    foreach ($account->roles as $rid => $role) {
        $roles .= "<li>".$role."</li>";
    }
    if (count($roles) > 0) {
        $user_profile['field_user_roles'] = array(
            '#entity_type' => 'custom',
            '#bundle' => 'custom',
            '#theme' => 'field',
            '#field_type' => 'text',
            '#title' => 'Roles',
            '#label_display' => 'above',
            '#field_name' => 'field_user_roles',
            '#markup' => '<ul>' . $roles . '</ul>',
            '#weight' => 5,
        );
    }

     ?>
  <?php print render($user_profile); ?>
</div>

Which is giving me this output (which is close):

enter image description here

The problem is that it doesn't seem to be using #markup to display the field.

I'm getting these errors which indicate I'm doing something wrong:

Notice: Undefined index: #items in template_preprocess_field() (line 1060 of /path/to/site/modules/field/field.module).

Warning: Invalid argument supplied for foreach() in template_preprocess_field() (line 1060 of /path/to/site/modules/field/field.module).

Notice: Undefined index: #view_mode in zurb_foundation_preprocess_field() (line 311 of /path/to/site/sites/all/themes/zurb_foundation/template.php).

I'm also using the Foundation Drupal template (v7.5) which seems to relate to the above errors.

  • Have you printed a vardump/dpm of $user? If so, please attach result. Also you shouldn't be using $account = user_load(arg(1)); for security reasons since it uses the URL for the uid. If your user is logged in (which they should be) you can use global $user; to load the user's object. – longboardnode Dec 30 '16 at 23:00
  • The $user object contains roles as expected, var_dumping the $roles array displays the expected results (the roles of the user that is being viewed). Wouldn't global $user; only load the user that is logged in, not the user they're viewing (as expected)? – Samsquanch Dec 30 '16 at 23:43
6
+50

Updated answer

Scrolling through the Drupal.org module library, I discovered Role expose. I have never used it, but it seems to do the trick as well:

Role Expose -module gives site administrators ability to expose user their own user roles. Roles are listed on user profile page. Users may be granted an option to view own roles or all users roles.

Role expose

Original answer

Looking at the render array, I feel you misunderstood a bit (unless you have configured a field on the user object where you already put a string of all his roles, but then you would not need the logic here)...

$user_profile['field_user_roles'] = array(
  '#entity_type' => 'custom',          // Nope, it is 'user'.
  '#bundle' => 'custom',               // Nope, it is 'user'.
  '#theme' => 'field',                 // Probably it is not a field, but a custom render element containing markup.
  '#field_type' => 'text',             // Probably not since it probably wasn't a field.
  '#title' => 'Roles',
  '#label_display' => 'above',
  '#field_name' => 'field_user_roles', // Probably not since it probably wasn't a field.
  '#markup' => '<ul>' . $roles . '</ul>',
  '#weight' => 5,
);

I guess it works better if you remove some of the data (see below).

On a small side note, logic should be avoided as much as possible within template files. So I'd recommend creating a small custom module and implementing hook_user_view_alter(). (If you are planning on supporting only one theme, you can also place it in the theme's template.php file. Use the theme name as the module name.)

function MODULENAME_user_view_alter(&$build) {
  // Obtain the account that user_view() stored for us.
  $account = $build['#account'];

  // Prepare roles string.
  $roles = '';
  foreach ($account->roles as $rid => $role) {
    $roles .= "<li>".$role."</li>";
  }

  if (count($roles) > 0) {
    $build['modulename_user_roles'] = array( // Prefix with module name to prevent collisions.
      '#type' => 'item',
      '#title' => 'Roles',
      '#markup' => '<ul>' . $roles . '</ul>',
      '#attributes' => array('class' => 'class-one class-two'),
    );
  }
}

Additionally you can implement hook_field_extra_fields() to expose the property on example.com/admin/config/people/accounts/display and choose its weight within the admin interface.

function MODULENAME_field_extra_fields() {
  $extra['user']['user'] = array(
    'display' => array(
      'modulename_user_roles' => array( // Make sure the name matches your custom property
        'label' => t('User roles'),
        'description' => t("Lists the user's roles."),
        'weight' => 5,
      ),
    )
  );

  return $extra;
}

Combined, the property should have been added to the $user_profile array and there is no more need to override the template file.

If you want to use the item_list, as proposed by Yogesh, your render array in MODULENAME_user_view_alter() should look something like this:

    $build['modulename_user_roles'] = array(
      '#title' => 'Roles',
      '#theme' => 'item_list',
      '#items' => $account->roles,
      '#type' => 'ul',
      '#attributes' => array('class' => 'class-one class-two'),
    );
  • This is exactly the kind of explanation and solution I was looking for. Thanks! – Samsquanch Jan 9 '17 at 14:07
  • Happy to learn it helped you! :) – Neograph734 Jan 9 '17 at 14:12
  • One thing -- the "Roles" label isn't showing up on the page, and there's no option for the placement of the label for the field in the 'Manage Display' tab of the user, is there a way to add that in? – Samsquanch Jan 9 '17 at 14:23
  • Did you implement the hooks in a custom module and clear the cache? – Neograph734 Jan 9 '17 at 14:25
  • Yes, this is what I'm seeing in 'Manage Display', and on the page. There's not a label showing up on the page or in the display options. – Samsquanch Jan 9 '17 at 14:29
2

You can use theme_item_list function to print it in lsit format, check sample below:

<div class="profile" <?php print $attributes; ?>>
<?php $account = user_load(arg(1)); ?>
<?php print theme('item_list', array('items' => $account->roles)); ?>
</div>

Or you can write your own html like below (not preferred):

<div class="profile" <?php print $attributes; ?>>
<?php
  $account = user_load(arg(1));

  // Below code wraps roles in <li> tag.
  $roles = '<ul><li>' . implode('</li><li>', $account->roles) . '</li></ul>';
  // Below code show roles separated by comma.
  // $roles = implode(', ', $account->roles);

  print '<ul>' . $roles . '</ul>';
?>
</div>
  • It looks like this would just put the roles under all the other profile fields, right? I was trying to add it to the $user_profile array so that it would keep consistent format and styling and I could use weight to move it around if needed. – Samsquanch Jan 6 '17 at 13:35
  • @Samsquanch, the way I've provided directly prints roles in template file, it won't affect your $user_profile styling as it is not modifying or overriding it. If you're looking for re-arranging from UI/weight @neograph734 solution is best suite. As it will add the Roles element to your user profile display and you can then re-arrange it as per your needs. – Yogesh Jan 7 '17 at 13:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.