Sprucing up your User Profile Pages

I recently launched a Drupal Codebase site for a programming community and wanted to have the user profiles to be more than just a "signed up on..." and a Tracker Tab. I wanted them to have structured and customisable blocks, dynamic content, a Peer to Peer Message Board (almost finished)... I can have my dreams cant I?!

I recently wrote a book page on how to programmatically create a view. I wanted to do this as it would allow to me control almost an entire website with multiple content types, terms and users (as well as combinations of the three) along with RSS feeds - all powered by the Views Module + a bolt on module consisting mostly of a menu callback and a function to make and configure a view. This worked pretty well for a first try and principle test!

I then realised - hey, if you can do this with Views - why cant you do it with Panels too? Panels are fantastically useful for structuring multiple blocks, views and nodes onto a page. So I tried… And you can!

I'm not going to bother doing it to THIS site as I'm the only user - pretty pointless. However it will be useful for those of you who have a user-driven website and want to have user profiles be a little more interesting.

Firstly, you want to define a few views. Currently (at time of writing), I have 2 - Most Recent Snippet and Nodes Comments On (I wanted Most Recent Comments, but Views wont do that for me AFAIK). Next, you need to override the theme_user_profile function in your template.php. This is the code I used:

//Initial Load
$panels->content = array();
$panels->access = array();
$panels->title = $account->name;
$panels->css_id = "css_id";
$panels->layout = "twocol";
 
 
//Users Code
$temparea = new StdClass();
$temparea->area = 'left';
$temparea->type = 'views';
$temparea->configuration = array(
  'view' => 'code_by_user',
  'type' => 'block',
  'pager_id' => 0,
  'nodes_per_page' => 20,
  'args' => $account->name,
  'url' => '',
  'show_title' => 1,
  );
$temparea->position = 1;
$panels->content[$temparea->area][] = $temparea;
 
 
//Users Comments
$temparea = new StdClass();
$temparea->area = 'right';
$temparea->type = 'views';
$temparea->configuration = array(
  'view' => 'comment_by_user',
  'type' => 'block',
  'pager_id' => 0,
  'nodes_per_page' => 20,
  'args' => $account->name,
  'url' => '',
  'show_title' => 1,
  );
$temparea->position = 1;
$panels->content[$temparea->area][] = $temparea;
 
 
 
 
$layouts = panels_get_layouts();
$layout = $layouts[$panels->layout];
$layout['css_id'] = $panels->css_id;
 
panels_is_panels_page(TRUE);
$content_types = panels_get_content_types();
 
foreach ($panels->content as $location => $list) {
  foreach ($list as $area) {
    $function = $content_types[$area->type]['callback'];
    if (function_exists($function)) {
      $content[$area->area] .= $function($area->configuration);
    }
  }
}
 
 
$output = panels_get_layout($layout, $content);
drupal_set_title(filter_xss_admin($panels->title));
return $output;

As you can see, first step is to initialise the panel settings - in this case I want to use the twocol panel layout along with the username as the panel title and the CSS ID of 'css_id' (original, eh). This is easy.

The next two steps are slightly more complex as they involve creating associative arrays of the panel. I've not investigated ALL of these types, but I found the easiest way was to unserialize and "print_r" the contents of one of the configuration fields from the panels_area table in the database. This can give you and idea of what goes in where. To embed a View, you can follow my example above with the value for the view key being the view id, type being the type of view output (eg, embed, block or page), pager_id being a uniquely identifiable value fpr multiple pagers on a page and so on - most of this can be found in the Drupal Views documentation.

Nearly there; next we grab the panel layouts and select the entry from the layouts array determined by our panels selection earlier on. We also set the CSS ID.

Following this we grab all the content types compatible with panels. We need to do this so we can find which callback we need to execute to get the data out of a "Views Panel" or a "Block Panel", etc. This will also check that the content type you've assigned to that panel actually HAS a valid and existing callback too. The results of the callback are appended into an array of strings where they key is the ID of the area you'd putting data into (eg 'left').

The final stage is to pass the layout and contents through the panels module, set the title of the page based on the panels configuration above (in this case, the user name) and then return the output.

If anyone has any suggestions for this - I'd happily take them on board. At some point over the next week or so, once I have all this ironed out 100% - I'll write it up as a book entry to go alongside my Creating a View Programmatically "tutorial".