Theming user profiles built with Content Profile
This is a fairly minor issue but hopefully this will prevent a couple of hours of headscratching for someone else out there! The site I am currently working on requires a reasonable amount of custom fields to be added to the users profile so Content Profile seemed to be the logical choice.
For those of you who do not know what Content Profile is, it is a module for Drupal 6 that picks up from where Node Profile left off in Drupal 5, it allows users to be displayed as nodes within the Drupal CMS. There continue to be arguments as to whether users should be stored as nodes in Drupal, but I will not get in to that argument here.
So, once I had built my registration form using CCK and had configured all the fields correctly, I went to view my new user profile page, it was a little boring but at least all the information was there but it was all a bit linear and boring so it was time to liven things up a little with some graphics! The newly built profile had a number of fields (such as social networking URLs, contact details ect) that lent themselves perfectly to being displayed grouped together on the users profile screen, my first reaction was to go and search the Content Profile module code to find a theming function to override but to my surprise there wasnt one! There are a few theming functions but not one for the actual view of the profile...hmmm... so, how to get around this? Add our own theming function, then override it! Ok, this isn't as scary as it sounds - heres what you need to do:
Find this code in content_profile.mode (in the beta4 release its around line 532):
/**
* Implementation of hook_theme().
*/
function content_profile_theme() {
return array(
'content_profile_display_view' => array(
'template' => 'content_profile-display-view',
'arguments' => array('element' => NULL),
'file' => 'content_profile.theme.inc',
),
'content_profile_display_add_link' => array(
'file' => 'content_profile.theme.inc',
),
'content_profile_display_link' => array(
'file' => 'content_profile.theme.inc',
),
'content_profile_display_tab_view' => array(
'file' => 'content_profile.theme.inc',
),
'content_profile_display_tab_edit' => array(
'file' => 'content_profile.theme.inc',
),
);
At the end of this (before the last closing bracket and semi-colon) you need to add:
'content_profile_view' => array(
'file' => 'content_profile.theme.inc',
),
This tells Drupal that there is a new theming function that it needs to use. The first line of this is the function name, and the 'file' is the file that our function will live in, make sense? Good, now we can write the function itself!
In content_profile.theme.inc we need to make some small changes. Locate the following function (around line 34)
/**
* Implementation of content_profile_preprocess_HOOK()
*/
function content_profile_preprocess_content_profile_display_view(&$variables) {
$element = $variables['element'];
$node = content_profile_load($element['#content_type'], $element['#uid']);
$variables['node'] = &$node;
$variables['uid'] = $element['#uid'];
$variables['type'] = $element['#content_type'];
$path = drupal_get_path('module', 'content_profile') .'/content_profile.css';
drupal_add_css($path, 'module', 'all', FALSE);
$variables['title'] = check_plain(node_get_types('name', $node->type));
$tabs = array();
if ($element['#edit_link']) {
$tabs[] = theme('content_profile_display_tab_view', $node);
$tabs[] = theme('content_profile_display_tab_edit', $node);
}
if (count($tabs) > 0) {
$variables['tabs'] = $tabs;
}
$variables['content'] = node_view($node, ($element['#style'] == 'teaser'), TRUE, TRUE);
}
Our problem lies in the last line, node_view does pretty much what it says on the tin, it presents the user with a very basic view of the information stored in that node, in order to do any theming beyond just prettying our profile up with CSS we need to change this line, so change this to the following:
$variables['content'] = theme('content_profile_view',$node,$element);
Then add our function:
function theme_content_profile_view($node,$element){
return node_view($node, ($element['#style'] == 'teaser'), TRUE, TRUE);
}
As you can see we haven't made any huge changes to the code, just re-routed things a little. The problem with the initial implementation is that when we get to the templating layer of drupal (.tpl files), each element of the user profile is wrapped up in the $content variable with no way of getting at them in order to wrap divs around them, or add classes etc. By doing it this way we actually pass the $node to the theming layer, giving us access to all of the fields as individual entities. I'm not sure why Content Profile does this and I think I may suggest a patch to the author, but until then I hope this has been useful!







Comments
I agree with David. You've
I agree with David. You've done a lovely job of laying this out, but a little more help would be amazing! I've been struggling with the content_profile for weeks trying to theme it with no luck. Print_r is of no help!
Great article
I'm pretty new to Drupal theming. Just installed the content profile module and trying to create a custom user reg form. I made the changes here you mentioned. Can you possibly give a small sample of what I should do next. I mean - what do I name the tpl file. Do I put it in my theme directory. Can you give a quick example. Say I want to keep Username and email, and I have custom fields for prefix,firstname, mi, lastname, and suffix, and for address 1, 2, city, state,zip, and country. I think if I see a good sample I can really get the whole concept.
Thanks!
:) David
Post new comment