is there a way to set buddylist module such that a user can only see the profile of his/her buddies and no one else's?
thanks

Comments

dldege’s picture

No.

I needed something like that on a previous project and had to write some custom code. Here is the overview of what I did.

1. I created fields using core profile module - for the ones I didn't want non-buddies to see I made them Private field, content only available to privileged users.
2. In access control all users are granted the permission access user profiles
3. Next I wrote custom code for hook_profile_alter that checked to see if the currently logged in user was a buddy of the $account being viewed. If so, I showed all "private" fields, if not I removed those from the profile view.

Here is the function for checking the "if buddy".

function _buddylistext_is_buddy($uid,$bid) {
  $isbuddy = db_result(db_query("SELECT * FROM {buddylist} WHERE uid = %d AND buddy = %d",$uid, $bid));
  return $isbuddy;
}

Maybe some version of this will be helpful for you.

omnyx’s picture

dldege - thanks, that's exactly what I was looking for.
I'm a newbie though... so I need some help with step 3.
I understand the logic behind it but don't see how I would implement it - i.e. where I would type what.
more details/pointing to the right direction/webpages would be helpful. I'm eager to learn!

cheers

dldege’s picture

You need to create a custom module to hold this code - don't worry its easy.

make a folder called omnyx in sites/all/modules/custom/
create a file call omnyx.info and put this code in it

name = omnyx
description = Change profile handling and other site modifications

then create file called omnyx.module and put this code in it.

<?php
function omnyx_profile_alter($account, &$fields) {
  global $user;

  drupal_set_message("WELCOME OMNYX=>" . drupal_to_js($fields));
  
  //HERES WHERE YOU COULD MAKE THE IS BUDDY CHECK - HARD CODED NOW
  $show_private = TRUE;
  
  if ($show_private) {
    $result = db_query('SELECT * FROM {profile_fields} WHERE visibility IN (%d)', PROFILE_PRIVATE);
    while ($field = db_fetch_object($result)) {
      // Mark the private field as public temporarily
      $field->visibility = PROFILE_PUBLIC;
      // Call profile module to format it
      if ($value = profile_view_field($account, $field)) {
        $title = ($field->type != 'checkbox') ? check_plain($field->title) : NULL;
        $item = array('title' => $title,
          'value' => $value,
          'class' => $field->name,
        );
        $fields[$field->category][$field->name] = $item;
      }
    }
  }
}

then enable the module on the modules page. Visit a user/X page and the private profile values should show up. You can customize the code to make the showing of the private fields based on the buddylist relationships of the users as mentioned before.

omnyx’s picture

thanks dldege...however, i'm still bumping into problems...
so i created 'buddyonly' directory and the two files ('buddyonly.module' and 'buddyonly.info')
now when I include the module in the administer section drupal just won't reload...and nothing happens...whatever page i try to access on drupal i just get a completely blank screen...
any ideas what it might be?

also i'm running drupal locally and it's 5.1 version.
cheers

dldege’s picture

White screen is usually a php error of some kind. Check your various apache log files - they might help track it down.

If you called the files buddyonly you need to replace omnyx with buddyonly in your functions - the name of the module is used to figure out the function names for hooks.

I tested the module under php 5 but I don't think anything is requiring php 5 in that code.

omnyx’s picture

thanks for follow-ups...
think I almost got it. Now, since I don't know PHP (yet! I started working on it) I thought something like this would work

function buddyonly_profile_alter($account, &$fields) {
  global $user;

 // drupal_set_message("WELCOME OMNYX=>" . drupal_to_js($fields));
// I needed to comment the upper line because it was listing the fields in error...is it ok if it's commented?

  function _buddylistext_is_buddy($uid,$bid) {
  $isbuddy = db_result(db_query("SELECT * FROM {buddylist} WHERE uid = %d AND buddy = %d",$uid, $bid));
  return $isbuddy;
}
 
// from here on everything works nicely..but i still don't know how i would 'call' for the _buddylistext_is_buddy function...after calling that //function I would get the appropriate value for $isbuddy.
 
 $show_private = FALSE;
 if($isbuddy) { $show_private = TRUE;}
 
  if ($show_private) {
    $result = db_query('SELECT * FROM {profile_fields} WHERE visibility IN (%d)', PROFILE_PRIVATE);
    while ($field = db_fetch_object($result)) {
      // Mark the private field as public temporarily
      $field->visibility = PROFILE_PUBLIC;
      // Call profile module to format it
      if ($value = profile_view_field($account, $field)) {
        $title = ($field->type != 'checkbox') ? check_plain($field->title) : NULL;
        $item = array('title' => $title,
          'value' => $value,
          'class' => $field->name,
        );
        $fields[$field->category][$field->name] = $item;
      }
    }
  }
}
omnyx’s picture

any feedback?
cheers

dldege’s picture

You can't have a function inside a function.

You need to move the _buddylistext_is_buddy function outside of the profile_alter function. The white screen is from a PHP error but you don't have error messages enabled (usually a good thing for a production server) so you aren't seeing the error.

That's my guess anyway.

omnyx’s picture

thanks...so i put the _buddylistext_is_buddy function outside the buddyonly_alter_profile function.
But I presume I need to check within the buddyonly_alter_profile function the buddy condition so I need to use the buddylistext_is_buddy function there. How would i properly 'execute' the function so that it changes the $isbuddy appropriately?

also, can you explain briefly what happens in the background? how does drupal know to run the buddyonly_alter_profile function and how does it know what the id of the user (call it user A) who sends the request is and what the id of the user whose profile user A wants to check?

cheers

dldege’s picture

function buddyonly_profile_alter($account, &$fields) {
  global $user;

// drupal_set_message("WELCOME OMNYX=>" . drupal_to_js($fields));
// I needed to comment the upper line because it was listing the fields in error...is it ok if it's commented?

  function _buddylistext_is_buddy($uid,$bid) {
  $isbuddy = db_result(db_query("SELECT * FROM {buddylist} WHERE uid = %d AND buddy = %d",$uid, $bid));
  return $isbuddy;
}

$isbuddy = _buddylistext_is_buddy($user->uid, $account->uid);

$show_private = FALSE;
if($isbuddy) { $show_private = TRUE;}

  if ($show_private) {
    $result = db_query('SELECT * FROM {profile_fields} WHERE visibility IN (%d)', PROFILE_PRIVATE);
    while ($field = db_fetch_object($result)) {
      // Mark the private field as public temporarily
      $field->visibility = PROFILE_PUBLIC;
      // Call profile module to format it
      if ($value = profile_view_field($account, $field)) {
        $title = ($field->type != 'checkbox') ? check_plain($field->title) : NULL;
        $item = array('title' => $title,
          'value' => $value,
          'class' => $field->name,
        );
        $fields[$field->category][$field->name] = $item;
      }
    }
  }
}

Drupal core calls hook_profile_alter everytime a profile is being viewed and passes the $account information being viewed. "Hooks" are called by looking at every module loaded for a function called "modulename_hook_name" so in this instance 'buddyonly_profile_alter'. Other modules could also provide a profile_alter hook.

I hope this gets it working for you.

omnyx’s picture

yep - works nicely. Thanks!
quick question: when the profile fields are made temporarily public does that mean that they are public server-wide? i.e. let's say A and B are buddies and C is not a buddy to B. Then what happens if A tries to check B's profile and succeeds since A is B's buddy. What happens if C tries to look up for B's profile at the same time? Would C be allowed to see it, since the $field->visibility becomes public?

also, if you have time (only if you have time, it's nothing too important) can you just explain in couple of words this part of the code:

 // Call profile module to format it
      if ($value = profile_view_field($account, $field)) {
        $title = ($field->type != 'checkbox') ? check_plain($field->title) : NULL;
        $item = array('title' => $title,
          'value' => $value,
          'class' => $field->name,

i.e. what exactly does it do?
cheers and thanks!

dldege’s picture

The fields are only made public locally during this function call and won't have any effect on other users viewing the same profile.

The chunk of code you are wondering was taken from the profile.module and simply builds the html for each profile field you are showing based on its type, etc. and adds it into the array of things to display. That is, the return value of the profile_alter function is a structured array of all the items that will be displayed on the rendered page.

Glad its working and hope you learned some stuff along the way.

omnyx’s picture

i did learn a lot, thanks!
it's good that the profile change is just local. But why is it so? Why does the change of profile visibility happening only here? Does it have to do with the order the profile_alter hooks are called?
i'm curious...please clarify if possible

dldege’s picture

Because I'm altering the local copies of the profile fields and data - not the database.

drupalina’s picture

subscribing