I'm working on a site where I need to count the number of times a user flags a book/mag for borrowing. The book/mag details are implemented using CCK and I'm using the flag module for the users to flag the books they require. I'll need to restrict the number of books a person can borrow at a time to two. So based on the post at http://drupal.org/node/955724 I created a module which contains the code below. But it doesn't seem to be doing anything. Tried figuring out what could be wrong but haven't had the luck. Would appreciate if someone could tell me what's wrong with this code snippet.

----------------------------------------------------------------------------------------------
<?php
// $Id$

// Because of the presence of the .info file this hook is optional but is provided nevertheless
function lw_help($path, $arg) {
$output = ''; //declare your output variable
switch ($path) {
case "admin/help#lw":
$output = '

'. t("Allows subscribers to borrow only one book at a time") .'

';
break;
}
return $output;
} // function lw_help

function lw_perm() {
return array('access library');
} // function lw_perm

function lw_flag($action, $flag, $content_id, $account) {
if ($action == 'flag' && !$flag->global) {
//currently checks for all flags instead of only borrows
$count = _count_borrow_flags($flag->name, $account->uid);
$flag->flag_message = format_plural($count, "You've marked 1 book for borrowing", "You're borrowing @count book. You are allowed to borrow only one at a time");
}
} // function lw_flag

function _count_borrow_flags($flag_name, $uid = NULL, $interval = 24) {
static $cache = array();
global $user;

if (!isset($uid)) {
$uid = $user->uid;
}

if (($flag = flag_get_flag($flag_name))) {
if ($flag->global) {
$uid = 0;
}
if (!isset($cache[$flag_name][$uid][$interval])) {
$cache[$flag_name][$uid][$interval] = db_result(db_query('SELECT COUNT(*) FROM {flag_content} WHERE fid = %d AND uid = %d AND timestamp > %d', $flag->fid, $uid, time() - 60*60 * $interval));
}
return $cache[$flag_name][$uid][$interval];
}
} //function _count_borrow_flags

----------------------------------------------------------------------------------------------

Best regards

Sridhar

Comments

mooffie’s picture

[I've deleted my comment: I'll return when I have more time and expand it.]

mooffie’s picture

Status: Fixed » Active

(1) You're using Flag 1.x. The hooks described in the document you linked to exist in Flag 2.x only. So they won't work for you.

(2) HOWEVER, you're going to be disappointed even after upgrading to Flag 2.x, because, as that document points out, using those hooks you can't show an error message to the user. Your users won't like it. It's one thing #952114: Have hook_flag_validate() will solve.

(3) An alternative solution: Implement hook_flag() and when you see that an item has been flagged, unflag it if more than 2 items (in your case) are already flagged. It ought to work in Flag 1.x as well. Here's code to get you started (use it as a starting point: I may have typos):

/**
 * Implements hook_flag().
 */
function MYMODULE_flag($action, $flag, $content_id, $account) {
  if ($flag->name == 'borrow' && $action == 'flag') {
    if ($flag->get_user_count($account->uid) > 2) {
      $flag->flag('unflag', $content_id, $account);
      $flag->flag_message = $flag->unflag_message = "You can only borrow 2 items at a time. Please unborrow some item first.";
    }
  }
}

(The document you used contains a complicated code to count the items but that's only because it counts over a span of time. In your case, since you want the total count, one method call is all that's needed.)

(One disadvantage of this snippet is that if some actions are triggered in the 'flag' event (e.g., unpublishing a node), they'll have to be undone. hook_flag_validate() won't have this problem.)

mooffie’s picture

Status: Active » Fixed

I added these clarifications to the document(s) you linked to.

sridharpandu’s picture

Status: Fixed » Active

@moffie Thanks a lot, your code works for restricting the number of borrows. Thanks once again for simplifying the approach.

However I noticed the following. When I try to flag the third book the error message is displayed as expected and the flag is not set. Behaviour is as expected.

Then I go to a previously flagged book and try to unflag it I get the following message
An HTTP error 200 occurred.
http://127.0.0.1/drupal6/?q=flag/unflag/borrow/4&destination=node%2F4&to...

Any attempt to flag a third book throws the same error after the above code is executed. I am not sure why. Will investigate and post my findings. Maybe you want to check at your end as well. I plan to improvise this module and post the code here.

Best regards

Sridhar

mooffie’s picture

An HTTP error 200 occurred.

This means a PHP error occured. Something inside the if() {} is wrong.

You're clicking the link with your left mouse button. So you can't see the errors. Open the link in a new window. Or disable JavaScript. And if you see a white screen, check your server's error log.

Maybe you want to check at your end as well

I don't have the time for this. I already said my code is only a starting point. Let us know what errors are printed (the _real_ error(s), not the one you quoted) and we'll try to help.

sridharpandu’s picture

Thanks a lot. Will check that out.

Best regards

Sridhar

mooffie’s picture

Status: Active » Fixed

I've checked the code I gave you and it works for me. So I'm marking this "fixed".

Re-open this when you have the error message.

IMPORTANT: The code has "$flag->get_user_count($account->uid)". This will work in Flag 1.x only. If you're using Flag 2.x, change this to "$flag->get_user_count($account->uid, flag_get_sid($account->uid))". (This won't be necessary when #1011048: $flag->get_user_count(): make 'sid' optional is fixed.)

sridharpandu’s picture

Status: Active » Fixed

@mooffie, Thanks a lot. I am checking it. I've noticed I don't get this error, or rather haven't got this error till date on slicehost. On my localhost I don't get this error if I open it in a new tab or new window. My initial impression is that it seems to be a PHP memory issue. My laptop has 128M set in PHP.ini while the slicehost has unlimited memory for PHP. No entry in error logs on my laptop. But access logs have the following entries. Will try and home in on the issue.

127.0.0.1 - - [31/Dec/2010:08:27:51 +0530] "GET /drupal6/misc/jquery.js?z HTTP/1.1" 200 16055 "http://127.0.0.1/drupal6/?q=node/2" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.12) Gecko/20101027 Ubuntu/10.10 (maverick) Firefox/3.6.1$
127.0.0.1 - - [31/Dec/2010:08:27:51 +0530] "GET /drupal6/misc/drupal.js?z HTTP/1.1" 200 3912 "http://127.0.0.1/drupal6/?q=node/2" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.12) Gecko/20101027 Ubuntu/10.10 (maverick) Firefox/3.6.12$

Best regards

Sridhar

Status: Fixed » Closed (fixed)

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

Anonymous’s picture

Any plans to move this into a module?

sridharpandu’s picture

@SuperDuperDan - Are you addressing the question to me or mooffie?

daniel-san’s picture

After searching for a way to create a simple voting system in which each user would only have 5 votes each, this code worked perfect. I wanted the simplicity of Flags to vote for items and did not find what I needed from any of the voting modules. This helped my tremendously. Thanks for the discussion and for sharing this code.