name == 'friend') {
switch ($event) {
case 'flag':
// See the status of the friendship.
$status = flag_friend_determine_friend_status($flag, $account->uid, $content_id);
// If both are now flagged, we record the relationship and remove the flags.
if ($status == 'both flagged') {
// Remove any message entries for either user.
flag_friend_message('unflag', $flag, $account->uid, $content_id);
flag_friend_message('unflag', $flag, $content_id, $account->uid);
// Since these users have flagged eachother, we create the relationship in the flag_friend table.
db_query("INSERT INTO {flag_friend} VALUES(%d, %d, %d)", $account->uid, $content_id, $_SERVER['REQUEST_TIME']);
// Then remove the flags.
$flag->flag('unflag', $content_id, $account);
$flag->flag('unflag', $account->uid, user_load(array('uid' => $content_id)));
}
break;
case 'unflag':
// Remove message.
flag_friend_message($event, $flag, $content_id, $account->uid);
break;
}
}
}
/**
* Implementation of hook_preprocess_flag().
*/
function flag_friend_preprocess_flag(&$vars) {
// this hook preprocesses ALL flag links, so make sure we have ours
if ($vars['flag']->name == 'friend') {
global $user;
// Determine what the status in the friend process is.
$status = flag_friend_determine_friend_status($vars['flag'], $user->uid, $vars['content_id']);
// Depending on the status, we need to manipulate the vars.
if ($status == 'pending') {
$vars['link_text'] = t('Pending - Cancel?');
$vars['flag_name_css'] = 'pending friend';
// TODO: some js to detect pending links and handle accordingly
}
if ($status == 'flagged') {
// Make this link into a remove link with
$vars['action'] = 'unflag';
$vars['link_href'] = str_replace('flag/confirm/', 'flag-friend/unfriend/', $vars['link_href']);
$vars['link_text'] = $vars['flag']->unflag_short;
}
if ($status == 'approval') {
$vars['link_text'] = t('Approve');
}
}
}
/**
* Implementation of hook_menu().
*/
function flag_friend_menu($may_cache) {
global $user;
$items = array();
if (!$may_cache) {
if ($user->uid) {
if (arg(0) == 'user' && is_numeric(arg(1))) {
// menu item to see message and respond
$items[] = array(
'path' => 'user/'. arg(1) .'/flag-friend',
'callback' => 'flag_friend_page',
'callback arguments' => array(user_load(array('uid' => arg(1)))),
'access' => user_access('access content'),
'type' => MENU_CALLBACK,
);
}
}
$items[] = array(
'path' => 'flag-friend',
'callback' => 'flag_friend_unfriend',
'access' => user_access('access content'),
'type' => MENU_CALLBACK,
);
}
return $items;
}
/**
* Menu callback for displaying friends
*/
function flag_friend_page($account) {
global $user;
$output = '';
// make sure that only you can see your own pending friends
if ($user->uid == $account->uid) {
drupal_set_title(t('My friends'));
$flag = flag_get_flag('friend');
// display a list of any pending friend requests
$flags = flag_friend_get_flags($flag, $account->uid);
if (!empty($flags)) {
$output .= theme('flag_friend_pending_flags', $account, $flags);
}
}
else {
drupal_set_title(t("@name's friends", array('@name' => $account->name)));
}
// display a list of this user's friends
$friends = flag_friend_get_friends($account->uid);
$output .= theme('flag_friend_friend_list', $account, $friends);
return $output;
}
/**
* Callback function to retrieve pending friend flags for theming.
*/
function flag_friend_get_flags($flag, $content_id, $reset = NULL) {
static $flagged_content;
$uid = $content_id;
$content_type = $flag->content_type;
if (!isset($flagged_content[$uid][$content_type][$content_id]) || $reset) {
$flags = flag_get_flags($flag->content_type);
$flagged_content[$uid][$content_type][$content_id] = array();
// get any flags that do not have messages
$result = db_query("SELECT * FROM {flag_content} WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id);
while ($new_flag = db_fetch_object($result)) {
$fcid = flag_friend_get_fcid($flag, $content_id, $new_flag->uid);
$flagged_content[$uid][$content_type][$content_id][$fcid] = $new_flag;
$flagged_content[$uid][$content_type][$content_id][$fcid]->user = user_load(array('uid' => $new_flag->uid));
}
// get flags with messages
$result = db_query("SELECT fc.*, ffm.message FROM {flag_content} fc INNER JOIN {flag_friend_message} ffm ON ffm.fcid = fc.fcid WHERE content_type = '%s' AND content_id = %d", $content_type, $content_id);
while ($new_flag = db_fetch_object($result)) {
$fcid = flag_friend_get_fcid($flag, $content_id, $new_flag->uid);
$flagged_content[$uid][$content_type][$content_id][$fcid] = $new_flag;
$flagged_content[$uid][$content_type][$content_id][$fcid]->user = user_load(array('uid' => $new_flag->uid));
}
}
return $flagged_content[$uid][$content_type][$content_id];
}
/**
* Callback function to retrieve a list of friends for the given user.
*/
function flag_friend_get_friends($uid, $reset = NULL) {
static $friends;
if (!isset($friends[$uid]) || $reset) {
$result = db_query("SELECT * FROM {flag_friend} WHERE uid = %d OR friend_uid = %d", $uid, $uid);
while ($friend = db_fetch_object($result)) {
// if the current user is in the uid column
if ($friend->uid == $uid) {
// load the friend_uid
$friends[$uid][$friend->friend_uid] = user_load(array('uid' => $friend->friend_uid));
}
else { // the current user is the friend_uid
// load the uid column as the friend
$friends[$uid][$friend->uid] = user_load(array('uid' => $friend->uid));
}
}
}
return $friends[$uid];
}
/**
* Theme function for the list of pending flags.
*/
function theme_flag_friend_pending_flags($account, $flags) {
// $account is the user of the page we're looking at
// $flag->user is the user requesting the relationship
$output = '';
$output .= t('
You have !friend_request.
', array('!friend_request' => format_plural(count($flags), 'a friend request', count($flags) .' friend requests')));
$output .= '';
$count = count($flags);
$output .= '- '. $count .' Pending Friend'. format_plural($count, '', 's') .'
';
$output .= '';
foreach ($flags as $flag) {
$output .= '';
$output .= '
'. theme('user_picture', $flag->user) .'
';
$output .= '
'. theme('username', $flag->user) .'';
$output .= '
'. $flag->message .'
'. flag_create_link('friend', $flag->user->uid) . flag_friend_create_link('unfriend', $flag->user->uid) .'
';
$output .= '
';
}
$output .= '
';
return $output;
}
/**
* Implementation of hook_user().
*/
function flag_friend_user($op, &$edit, &$account, $category = NULL) {
switch ($op) {
case 'form':
// The user account edit form is about to be displayed. The module should present the form elements it wishes to inject into the form.
$form = array();
$form['friend_notification'] = array(
'#type' => 'select',
'#title' => t('I would like to be notified when someone wants to be friends with me'),
'#multiple' => FALSE,
'#options' => array(0 => 'Yes', -1 => 'No'),
'#default_value' => isset($account->friend_notification) ? $account->friend_notification : 0,
'#weight' => -10,
);
return $form;
break;
}
}
/**
* Implementation of hook_user_link().
*/
function flag_friend_user_link($account) {
global $user;
// do not supply a link if the account and user are the same
if ($user->uid != $account->uid) {
$links = array();
$links['flag-friend'] = array(
'title' => flag_create_link('friend', $account->uid),
'html' => TRUE,
);
return $links;
}
}
/**
* Create a denial link.
*/
function flag_friend_create_link($type, $uid) {
if ($type == 'unfriend') {
$flag = flag_get_flag('friend');
$link = str_replace('Approve', 'Deny', str_replace('/flag-form/', '/flag-friend/', $flag->theme('unflag', $uid)));
return $link;
}
}
/**
* Theme function for the list of friends for the given user.
*/
function theme_flag_friend_friend_list($account, $friends) {
$output = '';
if (!empty($friends)) {
$output .= '';
foreach ($friends as $friend) {
$output .= '- ';
$output .= theme('user_picture', $friend);
$output .= '
';
}
$output .= '
';
}
else {
$output .= 'You have no friends, loser.';
}
return $output;
}
/**
* Menu callback to either unflag yourself, or remove the relationship record.
*/
function flag_friend_unfriend($event, $flag, $flag_name, $content_id, $token = NULL) {
global $user;
//die(print_r(func_get_args()));
// this might be a denial, in which case we unflag
if ($event == 'unflag') {
// the content_id is actually the account param in this case
$account = user_load(array('uid' => $content_id));
// and the $user->uid is actually the content(_id) we're unflagging
$content_id = $user->uid;
$flag = flag_get_flag($flag_name);
$flag->flag($event, $content_id, $account);
}
else {
// remove the friend relationship
db_query('DELETE FROM {flag_friend} WHERE (uid = %d AND friend_uid = %d) OR (uid = %d AND friend_uid = %d)', $user->uid, $content_id, $content_id, $user->uid);
}
drupal_goto();
}
/**
* Determines the status of the friendship by testing various conditions.
*
* @param object $flag
* The flag object.
*
* @param int $uid1
* The account id of one of the users.
*
* @param int $uid2
* The account id of the other user.
*
* @return
* A string describing the status of the relationship.
*
* NOTE: this could possibly go into hook_flag_access? once available.
*/
function flag_friend_determine_friend_status($flag, $uid1, $uid2) {
$you_are_flagged = $flag->is_flagged($uid1, $uid2);
$they_are_flagged = $flag->is_flagged($uid2, $uid1);
$friends = db_result(db_query("SELECT * FROM {flag_friend} WHERE (uid = %d AND friend_uid = %d) OR (uid = %d AND friend_uid = %d)", $uid1, $uid2, $uid2, $uid1));
// see if these users have flagged eachother
if ($you_are_flagged && $they_are_flagged) {
return 'both flagged';
}
else if ($friends) {
return 'flagged';
}
else if (!$you_are_flagged && !$they_are_flagged) {
return 'unflagged';
}
else if ($you_are_flagged && !$they_are_flagged) {
return 'approval';
}
else if (!$you_are_flagged && $they_are_flagged) {
return 'pending';
}
}
function flag_friend_form_alter($form_id, &$form) {
if ($form_id == 'flag_confirm' && $form['flag_name']['#value'] == 'friend') {
$action = $form['action']['#value'];
$flag = flag_get_flag('friend');
$content_id = $form['content_id']['#value'];
$token = $_REQUEST['token'];
switch ($action) {
case 'flag':
$flag_form = flag_friend_message_form($action, $flag, $content_id, $token);
$form = array_merge($flag_form, $form);
unset($form['actions']['submit']);
unset($form['actions']['cancel']);
$form['#submit']['flag_friend_form_submit'] = array();
break;
case 'unflag':
$unflag_form = flag_friend_unfriend_form($action, $flag, $content_id, $token);
$form = array_merge($form, $unflag_form);
$form['#submit']['flag_friend_form_submit'] = array();
break;
}
}
}
/**
* Form to send a message to a user before friend flagging.
*/
function flag_friend_message_form($action, $flag, $content_id, $token) {
$form['current'] = array('#type' => 'value', '#value' => func_get_args());
$form['flag_friend_message'] = array(
'#type' => 'textarea',
'#title' => t('Friend message (optional)'),
'#description' => t('Enter a message to send to this user.'),
'#cols' => 60,
'#rows' => 5,
);
$form['flag_friend_submit'] = array(
'#type' => 'submit',
'#value' => t('Send'),
'#suffix' => l('Cancel', $_GET['destination']),
);
$form['#theme'] = 'flag_friend_message_form';
return $form;
}
/**
* Form to confirm an unfriend flagging.
*/
function flag_friend_unfriend_form($action, $flag, $content_id, $token) {
$form['current'] = array('#type' => 'value', '#value' => func_get_args());
$question = t('Are you sure you want to !action?', array('!action' => $action));
$path = $_REQUEST['destination'];
$form = confirm_form($form, $question, $path);
$form['#redirect'] = 'flag/'. $action .'/'. $flag->name .'/'. $content_id .'/'. $token .'?'. drupal_get_destination();
$form['#theme'] = 'flag_friend_unfriend_form';
return $form;
}
/**
* Submit handler for message_form() and unfriend_form().
*/
function flag_friend_form_submit($form_id, $form_values) {
global $user;
$action = $form_values['current'][0];
$flag = $form_values['current'][1];
$content_id = $form_values['current'][2];
$account = $user;
$token = $form_values['current'][3];
if ($form_values['flag_friend_message']) {
$flag->friend_message = $form_values['flag_friend_message'];
}
flag_friend_message($action, $flag, $content_id, $account->uid);
$status = flag_friend_determine_friend_status($flag, $account->uid, $content_id);
flag_friend_message_email($status, $flag, $content_id, $account);
}
/**
* API callback function to update our new field.
*/
function flag_friend_message($action, $flag, $content_id, $account_uid) {
// see if the flag has an fcid
if (!isset($flag->fcid)) {
$flag->fcid = flag_friend_get_fcid($flag, $content_id, $account_uid);
}
if ($action == 'flag' && $flag->friend_message) {
db_query("INSERT INTO {flag_friend_message} VALUES(%d, '%s')", $flag->fcid, $flag->friend_message);
}
else if ($action == 'unflag') {
db_query("DELETE FROM {flag_friend_message} WHERE fcid = %d", $flag->fcid);
}
}
function flag_friend_message_email($status, $flag, $recipient_uid, $sender) {
$recipient = user_load(array('uid' => $recipient_uid));
if (isset($recipient->friend_notification) && $recipient->friend_notification != -1) {
$email = theme('flag_friend_message_email', $status, $flag, $recipient, $sender);
if (function_exists('messaging_message_send_user')) {
messaging_message_send_user($recipient, $email, NULL, 1);
}
else {
drupal_mail($email['type'], $recipient->mail, $email['subject'], $email['body']);
}
}
}
/**
* Theme the outgoing email message.
*
* @param string $status
* Status of the friendship.
*
* @param object $flag
* The flag object.
*
* @param object $recipient
* The user object of the person receiving the email.
*
* @param object $sender
* The user object of the person sending the email.
*
* @return
* An array containing the email [type] (mailkey), [subject] and [body].
*/
function theme_flag_friend_message_email($status, $flag, $recipient, $sender) {
$email = array();
$email['type'] = 'flag-friend';
switch ($status) {
case 'both flagged':
// sender confirmed you as a friend
$email['subject'] = t('!username confirmed you as a friend !site', array(
'!username' => $sender->name,
'!site' => 'on '. variable_get('site_name', ''),
));
$email['body'] = t('!firstname confirmed you as a friend on !site.\n\n
To view !firstname\'s profile, follow this link,\n
!link\n\n
!message\n\n
Thanks,\n
The !site Team', array(
'!firstname' => $sender->firstname ? $sender->firstname : $sender->name,
'!site' => variable_get('site_name', ''),
'!message' => $flag->friend_message ? 'Message:\n'. $flag->friend_message : '',
'!link' => url('user/'. $recipient->uid, NULL, NULL, TRUE),
));
break;
case 'pending':
// sender added you as a friend
$email['subject'] = t('!username added you as a friend !site', array('!username' => $sender->name, '!site' => 'on '. variable_get('site_name', '')));
$email['body'] = t('!firstname added you as a friend on !site. We need to confirm that you know !firstname in order for you to be friends on !site.\n\n
To confirm this friend request, follow the link below:\n
!link\n\n
!message\n\n
Thanks,\n
The !site Team', array(
'!firstname' => $sender->firstname ? $sender->firstname : $sender->name,
'!site' => variable_get('site_name', ''),
'!message' => $flag->friend_message ? 'Message:\n'. $flag->friend_message : '',
'!link' => url('user/'. $recipient->uid .'/flag-friend', NULL, NULL, TRUE),
));
break;
}
return $email;
}
/**
* Retrieves the fcid of a flag.
*
* NOTE: hopefully fcid will be passed into the hook_flag() at some point
* at which time will render this function unnecessary
*/
function flag_friend_get_fcid($flag, $content_id, $account_uid) {
return db_result(db_query("SELECT fcid FROM {flag_content} WHERE fid = %d AND content_type = '%s' AND content_id = %d AND uid = %d", $flag->fid, $flag->content_type, $content_id, $account_uid));
}
/**
* Retrieve our flag's message.
*/
function flag_friend_get_message($fcid) {
$flag_friend = FALSE;
$result = db_result(db_query("SELECT message FROM {flag_friend_message} WHERE fcid = %d", $fcid));
if ($result) {
$flag_friend = $result;
}
return $flag_friend;
}
/**
* Theme function for the message form.
*/
function theme_flag_friend_message_form($form) {
drupal_set_title('Send a friend request.');
return drupal_render($form);
}
/**
* Theme function for the unfriending action.
*/
function theme_flag_friend_unfriend_form($form) {
//drupal_set_title();
return drupal_render($form);
}
/**
* Implementation of hook_flag_default_flags().
*/
function flag_friend_flag_default_flags() {
$flags = array();
$flags[] = array(
'content_type' => 'user',
'name' => 'friend',
'title' => 'Friend',
'roles' => array(
0 => '2',
),
'global' => FALSE,
'flag_short' => 'Add friend',
'flag_long' => 'Add this user to your list of friends.',
'flag_confirmation' => 'Are you sure you want to add this user to your list of friends?',
'unflag_short' => 'Remove friend',
'unflag_long' => 'Remove this user from your list of friends.',
'unflag_confirmation' => 'Are you sure you want to remove this user from your list of friends?',
'status' => FALSE,
'link_type' => 'confirm',
'locked' => array('name', 'global', 'link_type'),
);
return $flags;
}