4

I am using Views Data Export to get data on my Drupal users into Excel. My site has a large number of roles (Roles A - Z), and some of these are important for user statistics.

The view I use for data export is a table of fields. I added Roles as follows:

user roles in views

This gives me something like RoleA, RoleC, RoleD, RoleI for each user. This sort of data is difficult to manipulate in Excel.

What I would like to do instead is to have a column in the table for each important role that has 1 if the user has the role, or 0 if the user does not have the role.

In other words, my table looks like this now:

sample excel start

But I want it to look like this in Views:

target excel

  • Are your roles fixed? You could accomplish this by brute force using a custom views field template and adding a field for each role to your view. This isn't automatically scalable though. – Adam Balsam Jul 25 '13 at 15:09
  • @AdamBalsam The roles have a decent probability of changing in the future. – Patrick Kenny Jul 25 '13 at 15:23
6
+50

Here's a solution using a simple module and a custom field template.

Overview

The view (obviously of the User Table) should only contain one field: User: Name. All of the other Role columns are generated by implementing HOOK_views_pre_view() with a loop for each defined role. The module also defines a custom function that compares the original output (comma-separated list of roles) and returns true if the list contains the current column's role.

The custom views field template simply calls the custom function for each column that corresponds to a role.

This solution will automatically scale if you add/delete roles and adjust if you rename/reorder roles etc.

Module File

You'll obviously need an info file too. I chose to name the module views_urt (User Role Table) - but you can name it whatever you want or include these functions in an existing custom module if you choose.

<?php
/**
 * Implements HOOK_views_pre_view().
 *
 * Adds a field to the User Roles view for each role defined.
 */
function views_urt_views_pre_view(&$view) {
  if ($view->name == 'user_roles') {
    $roles = views_urt_roles();
    $count = count($roles);
    for($i=0;$i<$count;$i++) {
      $view->display['default']->handler->options['fields']['rid_' . $i]['id'] = 'rid_' . $i;
      $view->display['default']->handler->options['fields']['rid_' . $i]['table'] = 'users_roles';
      $view->display['default']->handler->options['fields']['rid_' . $i]['field'] = 'rid';
      $view->display['default']->handler->options['fields']['rid_' . $i]['label'] = $roles[$i];

    }
  }
}

/**
 * Determines if a comma-seperated list of roles contains the role of the
 * current column.
 *
 * @param $pos integer
 *   The column corresponding to the $field->position value in the view.
 * @param $user_roles string
 *   Comma seperated list of Roles (haystack)
 * @return bool
 */
function views_urt_has_role($pos, $user_roles) {
  $pos = ($pos -1);
  $user_roles = explode(',', $user_roles);
  $defined_roles = views_urt_roles();
  foreach ($user_roles as $user_role) {
    if (trim($user_role) == $defined_roles[$pos]) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Helper function that returns an array of roles exluding "Anonymous" and
 * "Authenticated" user.
 *
 * @return array
 *   An array of roles.
 */
function views_urt_roles() {
  $roles = user_roles();
  array_shift($roles);
  array_shift($roles);
  return $roles;
}

Views Field Template File

This template should be picked up by all of the fields in this view for all of the displays. So, since my view is named user_roles, this template is named views-view-field--user-roles.tpl.php.

<?php
if ($field->field_alias == 'users_name') {
  print $output;
}
else {
  // We're assuming that this view only has one field (User: Name). All other
  // fields are generated by the HOOK_views_pre_view() function in the
  // `views_urt.module` and those should be passed through the
  // `views_urt_has_role` function which determines if the $output
  // (comma-seperated roles per user) contains the column role.
  print views_urt_has_role($field->position, $output);
}
?>

Sample Output

User Roles Table

  • Thanks, this did the trick. I have it all working now. A couple notes: 1) I couldn't figure out why the template wasn't working and I realized that was because I had put the template in the site theme folder, not the admin theme folder, and this is an admin view. 2) I had several other fields that I needed to add, so I needed to customize the code a little bit (changing the value of $i, etc.) but I was able to quickly develop a working view based on your code. Many thanks! – Patrick Kenny Jul 26 '13 at 12:23
2

I think another option is to build a custom view mode. You can implement hook_entity_info_alter:

function MYMODULE_entity_info_alter(&$entity_info) {
     $entity_info['user']['view modes']['VIEW_MODE_NAME'] = array(
        'label' => t('Display user relation to existing roles'),
        'custom settings' => TRUE,
      );
    }

Then you can attach your theme function:

function MYMODULE__view($entity, $type, $view_mode, $langcode){
  if ($enitity == 'user' && $view_mode == 'VIEW_MODE_NAME') {
   // add some additional variables for template
    $node->content['#theme'] = 'VIEW_MODE_NAME_view';
  }
}

and in your theme function VIEW_MODE_NAME_view:

   function  VIEW_MODE_NAME_view_theme(){
     // get all role and display the entity and 
     //its roles the way you described    
    }

Once you have your view mode working you can use it in views (any view) as well as any other place where the entity is rendered.

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.