--- userpoints_flag.module
+++ (clipboard)
@@ -1,123 +1,214 @@
 <?php
+//$Id$
+
 /**
- * Implementation of hook_form_alter().
- *
- * Extends User Points module with Flag settings.
- */
-function userpoints_flag_form_alter(&$form, $form_state, $form_id) {
-  if ($form_id == 'userpoints_admin_settings') {
-    // Shift system_settings_form buttons.
-    $weight = $form['buttons']['#weight'];
-    $form['buttons']['#weight'] = $weight + 1;
-    
-    $group = "flagapi";
-    $form[$group] = array(
+ * Implementation of hook_userpoints().
+ */
+function userpoints_flag_userpoints($op, $params = array()) {
+  switch ($op) {
+    case 'setting':
+    $form['flag'] = array(
       '#type' => 'fieldset',
+      '#theme' => 'userpoints_flag_settings',
       '#title' => t('Flag settings'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
-      '#description' => t(''),
     );
-    
-    $form[$group][userpoints_flag_moderation] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Moderate votes'),
-      '#default_value' => variable_get(userpoints_flag_moderation, 0),
-      '#description' => t('Moderate User Points earned from votes.'),
+
+    // Load the category list.
+    $tree = taxonomy_get_tree(userpoints_get_vid());
+    $category_options = array();
+    $category_options[0] = t('!Uncategorized', userpoints_translation());
+    if (!empty($tree)) {
+      foreach ($tree as $term) {
+        $category_options[$term->tid] = str_repeat('--', $term->depth) . $term->name;
+      }
+    }
+
+    foreach(flag_get_flags() as $flag) {
+      $form['flag']['userpoints_flag_flagger_'. $flag->name] = array(
+        '#type' => 'textfield',
+        '#default_value' => variable_get('userpoints_flag_flagger_'. $flag->name, 0),
+        '#size' => 5,
+        '#maxlength' => 5,
+      );
+
+      $form['flag']['userpoints_flag_flagger_category_'. $flag->name] = array(
+        '#type' => 'select',
+        '#options' => $category_options,
+        '#default_value' => variable_get('userpoints_flag_flagger_category_'. $flag->name, 0),
+      );
+
+      $form['flag']['userpoints_flag_author_'. $flag->name] = array(
+        '#type' => 'textfield',
+        '#default_value' => variable_get('userpoints_flag_author_'. $flag->name, 0),
+        '#size' => 5,
+        '#maxlength' => 5,
+      );
+
+      $form['flag']['userpoints_flag_author_category_'. $flag->name] = array(
+        '#type' => 'select',
+        '#options' => $category_options,
+        '#default_value' => variable_get('userpoints_flag_author_category_'. $flag->name, 0),
+      );
+
+      $form['flag']['userpoints_flag_daily_limit_'. $flag->name] = array(
+        '#type' => 'textfield',
+        '#default_value' => variable_get('userpoints_flag_daily_limit_'. $flag->name, 0),
+        '#size' => 5,
+      );
+
+      $form['flag']['userpoints_flag_moderate_'. $flag->name] = array(
+        '#type' => 'checkbox',
+        '#default_value' => variable_get('userpoints_flag_moderate_'. $flag->name, 0),
+      );
+    }
+
+    // Add some definitions at the bottom to help clarify what things mean.
+    $form['flag']['userpoints_flag_help'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Userpoints Flag Help'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
     );
-    
-    $form[$group][userpoints_flag_vote] = array(
-        '#type'          => 'textfield',
-        '#title' => t('!Points for flag', userpoints_translation()),
-        '#default_value' => variable_get(userpoints_flag_vote, 1),
-        '#size'          => 5,
-        '#maxlength'     => 5,
+
+    $form['flag']['userpoints_flag_help']['info'] = array(
+      '#value' => '
+      <dl><dt>Flagger Points</dt><dd>These points are given to the user who is doing the flagging.</dd></dl>
+      <dl><dt>Flagger Category</dt><dd>This is the category to which "Flagger Points" are added.</dd></dl>
+      <dl><dt>Author/User Points</dt><dd>These points are given to the user who is either the author of the node or comment being flagged, or the user that is being flagged, depending on the flag type.</dd></dl>
+      <dl><dt>Author/User Category</dt><dd>This is the category to which "Author/User Points" are added.</dd></dl>
+      <dl><dt>Daily limit (flags)</dt><dd>This is the number of flags (not points) that a user may set within any twenty four hour period and still have points awarded.  If the user exceeds this number of flags the flag action will still be successful, but no points will be awarded to either the flagger or the author/user.</dd></dl>
+      <dl><dt>Moderate</dt><dd>Points will need to be approved by a moderator if this is selected.</dd></dl>',
     );
-    
-    $form[$group][userpoints_flag_author_node_vote] = array(
-        '#type'          => 'textfield',
-      '#title' => t('!Points to node author', userpoints_translation()),
-        '#default_value' => variable_get(userpoints_flag_author_node_vote, 0),
-        '#size'          => 5,
-        '#maxlength'     => 5,
-		'#description' => t('Select 0 to ignore.'),
-    );	
-	
-    $form[$group][userpoints_flag_author_comment_vote] = array(
-        '#type'          => 'textfield',
-      '#title' => t('!Points to comment author', userpoints_translation()),
-        '#default_value' => variable_get(userpoints_flag_author_comment_vote, 0),
-        '#size'          => 5,
-        '#maxlength'     => 5,
-		'#description' => t('Select 0 to ignore.'),
-    );	
-	
-    $form[$group][userpoints_flag_daily_threshold] = array(
-      '#type' => 'select',
-      '#title' => t('Daily threshold'),
-      '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50)),
-      '#default_value' => variable_get(userpoints_flag_daily_threshold, 0),
-      '#description' => t('The maximum number of votes -- that will earn User Points -- in a 24-hour period.<br />Select 0 to ignore.'),
+
+    return $form;
+  }
+}
+
+/**
+ * Implementation of hook_theme().
+ */
+function userpoints_flag_theme() {
+  return array(
+    'userpoints_flag_settings' => array('form' => NULL)
+  );
+}
+
+/**
+ * Theme the userpoints flag settings form.
+ */
+function theme_userpoints_flag_settings($form) {
+  $rows = array();
+  foreach (flag_get_flags() as $flag) {
+    $row = array(
+      $flag->name,
+      drupal_render($form['userpoints_flag_flagger_'. $flag->name]),
+      drupal_render($form['userpoints_flag_flagger_category_'. $flag->name]),
+      drupal_render($form['userpoints_flag_author_'. $flag->name]),
+      drupal_render($form['userpoints_flag_author_category_'. $flag->name]),
+      drupal_render($form['userpoints_flag_daily_limit_'. $flag->name]),
+      drupal_render($form['userpoints_flag_moderate_'. $flag->name]),
     );
+    $rows[] = $row;
   }
+
+  $header = array(
+    t('Flag type'),
+    t('Flagger !Points', userpoints_translation()),
+    t('Flagger Category'),
+    t('Author/User !Points', userpoints_translation()),
+    t('Author/User Category'),
+    t('Daily limit (flags)'),
+    t('Moderate')
+  );
+
+  $output = theme('table', $header, $rows);
+  $output .= drupal_render($form);
+
+  return $output;
 }
 
 /**
  * Implementation of hook_flag().
- *
  */
- 
-function userpoints_flag_flag($action, $flag, $content_id, $account) { 
-  
-  //points author - content_id
-  $author_points = 0;
-  if ($flag->content_type == 'node') {  
-    $author_points = variable_get(userpoints_flag_author_node_vote, 0);
-    $uid = _userpoints_flag_get_node_author($content_id);
-  } else if ($flag->content_type == 'comment') {
-    $author_points = variable_get(userpoints_flag_author_comment_vote, 0);
-    $uid = _userpoints_flag_get_comment_author($content_id);
-  }
-  
-  //no points for author
-  if ($uid != $account->uid) {
-      $threshold = variable_get(userpoints_flag_daily_threshold, 0);
-	  if (($threshold == '0') OR (_userpoints_flag_within_threshold($account->uid, $threshold))) {
-		  userpoints_userpointsapi(array(
-		    'uid'       => $account->uid,
-		    'points'    => ($action == 'flag' ? variable_get(userpoints_flag_vote, 1): -1 * variable_get(userpoints_flag_vote, 1)),
-		    'moderate' => variable_get(userpoints_flag_moderation, 0),
-		    'entity_id' => $content_id,
-		    'entity_type' => $flag->content_type,
-		    'operation'     => 'flag',
-		    'description' => t('Flag cast: !content_type !content_id.',array('!content_type'=> $flag->content_type, '!content_id'=> $content_id)),
-		    )
-		  );
-		  if (($author_points != 0) AND ($uid != 0)) {
-		    userpoints_userpointsapi(array(
-		    'uid'       => $uid,
-		    'points'    => ($action == 'flag' ? $author_points: -1 * $author_points),
-		    'moderate' => variable_get(userpoints_flag_moderation, 0),
-		    'entity_id' => $content_id,
-		    'entity_type' => $flag->content_type,
-		    'operation'     => 'flag author',
-		    'description' => t('Flag author cast: !content_type !content_id.',array('!content_type'=> $flag->content_type, '!content_id'=> $content_id)),
-		    )
-		    );
-		  }
-	  }
+function userpoints_flag_flag($action, $flag, $content_id, $account) {
+  $flagger_points = variable_get('userpoints_flag_flagger_'. $flag->name, 0);
+  $author_points = variable_get('userpoints_flag_author_'. $flag->name, 0);
+
+  // Only do something if points have been assigned to this flag type.
+  if ($flagger_points != 0 || $author_points != 0) {
+
+    // Get the user id of the content author or flagged user.
+    switch ($flag->content_type) {
+      case 'node':
+        $author_uid = _userpoints_flag_get_node_author($content_id);
+        break;
+      case 'comment':
+        $author_uid = _userpoints_flag_get_comment_author($content_id);
+        break;
+      case 'user':
+        $author_uid = $content_id;
+        break;
+    }
+
+    // Don't give points if the flagger is the author.
+    if ($author_uid != $account->uid) {
+
+      // Don't give points to the flagger or author if the flagger has exceeded the daily flagging limit for this flag type.
+      $flag_limit = variable_get('userpoints_flag_daily_limit_'. $flag->name, 0);
+      if (($flag_limit == 0) || (_userpoints_flag_within_limit($account->uid, $flag->fid, $flag_limit))) {
+
+        // Give points to the flagger.
+        if ($flagger_points != 0) {
+          userpoints_userpointsapi(array(
+            'uid' => $account->uid,
+            'tid' => variable_get('userpoints_flag_flagger_category_'. $flag->name, 0),
+            'points' => ($action == 'flag' ? $flagger_points : -1 * $flagger_points),
+            'moderate' => variable_get('userpoints_flag_moderate_'. $flag->name, 0),
+            'entity_id' => $content_id,
+            'entity_type' => $flag->content_type,
+            'operation' => 'flag_'. $flag->name,
+            'description' => t('Flag: !content_type !content_id.',array('!content_type'=> $flag->content_type, '!content_id'=> $content_id)),
+          ));
+        }
+
+        // Give points to the author or flagged user.
+        if (($author_points != 0) && ($author_uid != 0)) {
+          userpoints_userpointsapi(array(
+            'uid' => $author_uid,
+            'tid' => variable_get('userpoints_flag_author_category_'. $flag->name, 0),
+            'points' => ($action == 'flag' ? $author_points : -1 * $author_points),
+            'moderate' => variable_get('userpoints_flag_moderate_'. $flag->name, 0),
+            'entity_id' => $content_id,
+            'entity_type' => $flag->content_type,
+            'operation' => 'flag_author_'. $flag->name,
+            'description' => t('Flag author: !content_type !content_id.',array('!content_type'=> $flag->content_type, '!content_id'=> $content_id)),
+          ));
+        }
+      }
+    }
   }
 }
 
+/**
+ * Get the user id of the author of a node.
+ */
 function _userpoints_flag_get_node_author($nid) {
- return db_result(db_query("SELECT uid FROM {node} WHERE nid = %d LIMIT 1", $nid)); 
+  return db_result(db_query_range("SELECT uid FROM {node} WHERE nid = %d", $nid, 0, 1));
 }
 
+/**
+ * Get the user id of the author of a comment.
+ */
 function _userpoints_flag_get_comment_author($cid) {
- return db_result(db_query("SELECT uid FROM {comments} WHERE cid = %d LIMIT 1", $cid)); 
+  return db_result(db_query("SELECT uid FROM {comments} WHERE cid = %d", $cid));
 }
 
-function _userpoints_flag_within_threshold($uid, $threshold) {
-  $number = db_result(db_query("SELECT COUNT(*) FROM {flag_content} WHERE uid = %d AND timestamp > %d", $uid, time() - 86400));
-  return ($number <= $threshold ? TRUE : FALSE);
-}
\ No newline at end of file
+/**
+ * Find out whether the flagger has flagged a particular flag type more than a set number of times.
+ */
+function _userpoints_flag_within_limit($uid, $flag_id, $flag_limit) {
+  $flag_count = db_result(db_query("SELECT COUNT(*) FROM {flag_content} WHERE uid = %d AND fid = %d AND timestamp > %d", $uid, $flag_id, time() - 86400));
+  return ($flag_count <= $flag_limit ? TRUE : FALSE);
+}
