Community Documentation

Coding example: Limiting the number of flaggings per day

Last updated August 9, 2012. Created by mooffie on October 28, 2010.
Edited by joachim, xjm. Log in to edit this page.

Say you want to limit the number of times per day a user may flag items. (A use-case example: you don't want users to mark too many things as "spam".)

The first step is to find out the number of times a certain user has flagged items during, say, the last 24 hours. The following function does this:

<?php
/**
* Returns the number of flaggings the user made during the
* last 24 hours.
*/
function _count_last_flaggings($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];
  }
}
?>

Note that this code is meaningful for non-global flags only, because global flags don't records the flagging each user makes individually.

Usage example

Let's test our function. First, put it in some custom module.

We'll add a block to our page that prints for the currently authenticated user the number of bookmarks that use made today:

Create a new block. Choose the PHP input filter. Use the following code:

<?php
$count
= _count_last_flaggings('bookmarks');
print
format_plural($count, "You've bookmarked 1 time today.", "You've bookmarked @count times today.");
?>

Another example

Say we want to print a message after the user flags something that displays the number of items that user has displayed today:

Put the following in a custom module. Rename "MYMODULE" to the name of your module.

<?php
/**
* Implements hook_flag().
*/
function MYMODULE_flag($action, $flag, $content_id, $account) {
  if (
$action == 'flag' && !$flag->global) {
   
$count = _count_last_flaggings($flag->name, $account->uid);
   
$flag->flag_message = format_plural($count, "You've flagged 1 time today.", "You've flagged @count times today.");
  }
}
?>

Advanced example

Say we want to prevent our users from flagging too many items per day. We'll use hook_flag_access() (and hook_flag_access_multiple()) for this.

Note, however, that hook_flag_access() has some disadvantages. In short, it's not optimal tor "interactive use": we can't show nice error messages to the user. You'll also want to disable JavaScript for this flag (because we want to make invalid links disappear, so we need the page to refresh.)

There's a proposed feature, #952114: Have hook_flag_validate(), that will solve all these problems and will make things much simpler. But in the meantime we have to do with hook_flag_access().

2010-Dec-29: Clarification: The only reason this page uses the hook_access() mechanism is because hook_flag_validate() is not ready at the time of this writing, and also to serve as an example. Meanwhile people may also use the alternative shown here.

Put the following in a custom module. Rename "MYMODULE" to your module name.

<?php
// Update this number to your liking.
define('MAX_FLAGGINGS_PER_DAY', 10);

/**
* Implementation of hook_flag_access().
*
* Revoke access to this flag if the user has used up his quota.
*/
function MYMODULE_flag_access($flag, $content_id, $action, $account) {
  if (
$flag->name == 'bookmarks') {
   
$count = _count_last_flaggings($flag->name, $account->uid);
    if (
$count >= MAX_FLAGGINGS_PER_DAY) {
      return
FALSE;
    }
  }
}

/**
* Implementation of hook_flag_access_multiple().
*
* Revoke access to this flag if the user has used up his quota.
*/
function MYMODULE_flag_access_multiple($flag, $content_ids, $account) {
 
$access = array();

  if (
$flag->name == 'bookmarks') {
   
$count = _count_last_flaggings($flag->name, $account->uid);
    if (
$count >= MAX_FLAGGINGS_PER_DAY) {
      foreach (
$content_ids as $id => $action) {
       
$access[$id] = FALSE;
      }
    }
  }
   
  return
$access;
}
?>

Why not start a "Flag Flood" module?

An excellent idea. The code above could be easily generalized and made into a contrib module. This way you, the reader, won't inject the voodoo code above into too interesting places in your website and make the life of the programmer/themer that comes after you miserable.

Comments

Limiting the number of flaggings per day

Hi,
Using the first example I am getting 1 flag for anonymous user even if user did not flag anything.
The count for logged in users works ok. Any thoughts? Thank you

Limit Flags per User

Originally I looking for a way to limit users on the amount of flagging per entity type. The approach above looks like it will accomplish the same result? (is that true?) I suppose instead of using a 24 hour cycle I could extend that until the event starts? If for example if it were a month away I could code that in? (if so could someone post an example?)

More info:

I have a view that displays 50 node titles (for the PGA US Open that starts in June and I want users to flag a limited amount of Golfers) of the same content type and I want to create a component so users may flag (using VBO) a limit of 5 only? After that I may clone the component and change it from 5 to 1 or 10 or 20 this way I may apply these components to more views assigning them inside a VBO field?

I have been coding for 6 months and it looks like the only way for me to achieve this solution is to write a module any help would be greatly appreciated? Meanwhile I am going to give this a start thank you for posting this code with out it I would have no idea how to start this.

Dustin Dinsmore
theblizzardofodds.com

About this page

Drupal version
Drupal 6.x
Audience
Programmers

Structure Guide

Drupal’s online documentation is © 2000-2013 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License. Comments on documentation pages are used to improve content and then deleted.
nobody click here