I am using the bio module together with a custom profile-node module to replace user profiles. Now, I've recently added the "favorite nodes" module to my site, which uses hook_user to add a favorites list to the user profile. Basically, I would like to access that information when creating my custom node to include it in the profile page.

At this point, this information is lost when bio_profile_alter unsets all fields except for the one containing my custom node, and I couldn't see any way to access the $fields information during the node creating in bio_user.

I've solved the problem by hacking into the bio module, basically moving the node creation from bio_user to bio_profile_alter and attaching the $fields variable to the custom node being created. (See code below). Is this the most straight-forward solution possible, or am I missing out on something much simpler (i.e. without hacking bio?)?

I'm not entirely sure if this doesn't break any other functionality in bio, but if not, possibly this could be patched into the official version, as it provides extra functionality and improves speed in two ways: (1) no need for node_load to be called twice in bio_user and bio_profile_alter and (2) through the extra functionality, module developers / themers won't need to manually call external modules a second time to get information to be included in a profile node.

Thanks + let me know what you think.

Karl Moritz

/**
 * Implementation of hook_profile_alter().
 */
function bio_profile_alter(&$account, &$fields) {
  // Replace user profile with user bio.
  if (variable_get('bio_profile_takeover', 0) && $bio = bio_for_user($account->uid)) {
	  
	  $node = node_load($bio);
	  $name = node_get_types('name', bio_get_type());
    $node->profile_fields = $fields;
    
    $fields[$name]['bio']['value'] = node_view($node, FALSE, TRUE, FALSE);
    
    $typename = node_get_types('name', bio_get_type());
    foreach ($fields as $key => $val) {
      if ($key != $typename) {
        unset($fields[$key]);
      }
    }
    $account->name = $bio->title;
  }
}

If profile takeover is enabled, hook_user will not do anything on "view":

/** 
 * Implementation hook_user().
 */
function bio_user($op, &$edit, &$account, $category = NULL) {
  // If there's no bio for this user, nothing to do here.
  if (!$nid = bio_for_user($account->uid)) {
    return;
  }

  switch ($op) {
    case 'view':
      // Add bio to main user profile page, if option is enabled and bio is accessible.
      if (variable_get('bio_profile', 0) && !variable_get('bio_profile_takeover', 0) && node_access('view', $node = node_load($nid))) {
        $name = node_get_types('name', bio_get_type());
        $bio[$name]['bio']['value'] = node_view($node, FALSE, TRUE, FALSE);
        return $bio;
      }
      break;
    case 'delete':
      node_delete(bio_for_user($account->uid));
      break;
  }
}

Code is taken from the last stable version (5.x-1.2), apologies for pasting the changes like this rather than as patch - still have to figure out how to create such files at some point.

Comments

karlmoritz’s picture

Apologies,

the line $account->name = $bio->title;

should be $account->name = $node->title;

dww’s picture

Assigned: Unassigned » dww
Status: Active » Fixed

Some random thoughts/comments:

A) re: making patches:
http://drupal.org/patch
http://drupal.org/patch/create
http://drupal.org/patch/submit

B) node_load() caches its own results, so there's really no harm in having to call it twice during the same page load.

C) It sounds like what you're doing is rather scary -- you're using a module that's injecting other fields into the core user profile, and trying to replicate those in the bio node itself. However, you're not actually putting this data into the bio node -- for example, you couldn't make a view of this stuff, since they're not really fields in your bio node type.

If all you really want is to see both the bio fields *and* the other fields being added by this other module, all you need is the following configuration:

[x] Use bio for user profiles
[ ] Takeover profile.

That way, the bio fields will be listed on the user/N page, but so will the other fields in the regular core profile. I use this on the site I'm running with bio, since I'm using OG and I want to see the groups a user is subscribed to on their own user/N page, but I also want the bio fields visible. Sounds like much the same use-case...

karlmoritz’s picture

Thank you for your answer.

Regarding points (A) and (B), fair point on node_load() and I promise to look into patching :)

As for (C), I'm not sure if scary is exactly the correct term, but I suppose my hack is not very much conforming to the drupal way. The problem I had with the solution that you suggested, is that using that method I will get the fields from the other modules but the fully loaded node for the bio data, making it rather difficult to combine the two sets of data elegantly.

In my specific scenario, I'm using a favorite nodes module, which sends me an array of nodes, which I want to include in a table within the profile (rather than append to the end). I suppose I could use some div/css magic to position it in the right place, but would rather avoid that option.

Thanks,
kmh

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.