Flagging for other users

For this project, I needed to create a way for admins to recommend items to other users. In other words, bookmark a page for someone else.

Drupal 7 already has a great module for bookmarking, called Flag. It allows users to 'flag' content to say they like it (similar to Facebook) or to bookmark it for future reference. But it does not come out for the box with links to flag for other users.

For this site, I needed to create several admin pages with forms - one to send bookmarks to a user, and another to bookmark pages for a specific user. We won't discuss those here, as they are easy to create for yourself (hook_menu and write up simple forms to search for pages to recommend).

The flag link could not be used because the callback linked to always calls the global $user. So this theme function returns a link to our rewritten recommendation function.

/**
* rewrite of the regular flag theme to output a useful recommendation link
*/
function recommendations_theme_flag($uid, $nid, $action, $loc) {
	$token = drupal_get_token($nid);
	$flag = flag_get_flag('recommend');

	return ''.
		l($flag->{$action.'_short'}, 'recommendations/flag/'.$action.'/recommend/'.$nid.'/'.$uid,
			array('html' => true, 'query' => array('destination' => $loc, 'token' => $token)))
	.'';
}

The function to (un)set the flag from the base module calls the global $user, not allowing a another user to have flags set for them. So that has been rewritten.

/**
* Menu callback for (un)flagging a node.
*
* Used both for the regular callback as well as the JS version.
*
* TAKEN FROM FLAG.MODULE
* modified to handle any user instead of just the global user
*/
function recommendations_flag_page($action, $flag, $content_id, $uid) {
	$user = user_load($uid);

	// Shorten up the variables that affect the behavior of this page.
	$js = isset($_REQUEST['js']);
	$token = $_REQUEST['token'];

	// Specifically $_GET to avoid getting the $_COOKIE variable by the same key.
	$has_js = isset($_GET['has_js']);

	// Check the flag token, then perform the flagging.
	if (!flag_check_token($token, $content_id)) {
		$error = t('Bad token. You seem to have followed an invalid link.');
	}
	elseif ($user->uid == 0 && !$has_js) {
		$error = t('You must have JavaScript and cookies enabled in your browser to flag content.');
	}
	else {
		$result = $flag->flag($action, $content_id);
		if (!$result) {
			$error = t('You are not allowed to flag, or unflag, this content.');
		}
	}

	// If an error was received, set a message and exit.
	if (isset($error)) {
		if ($js) {
			drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8');
			print drupal_json_encode(array(
				'status' => FALSE,
				'errorMessage' => $error,
			));
			exit;
		}
		else {
			drupal_set_message($error);
			drupal_access_denied();
			return;
		}
	}

	// If successful, return data according to the request type.
	if ($js) {
		drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8');
		$flag->link_type = 'toggle';
		print drupal_json_encode(array(
			'status' => TRUE,
			'newLink' => $flag->theme($flag->is_flagged($content_id) ? 'unflag' : 'flag', $content_id, TRUE),
			// Further information for the benefit of custom JavaScript event handlers:
			'contentId' => $content_id,
			'contentType' => $flag->content_type,
			'flagName' => $flag->name,
			'flagStatus' => $flag->is_flagged($content_id) ? 'flagged' : 'unflagged',
		));
		exit;
	}
	else {
		flag($action, $flag->name, $content_id, $user);
		drupal_set_message($flag->get_label($action . '_message', $content_id));
		drupal_goto();
	}
}

Special thanks to the flag module.

Category: