Index: modules/voting/voting.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/voting/voting.module,v
retrieving revision 1.5
diff -u -r1.5 voting.module
--- modules/voting/voting.module	9 Sep 2005 19:01:38 -0000	1.5
+++ modules/voting/voting.module	2 Mar 2006 18:57:19 -0000
@@ -24,13 +24,14 @@
  */
 function voting_menu($type) {
   $items = array();
+  
   $items[] = array(
     'path' => 'voting/flash',
     'title' => t('voting'),
     'callback' => 'voting_flash',
     'access' => user_access('access content'),
     'type' => MENU_CALLBACK);
-  
+
   return $items;
 }
 
@@ -39,50 +40,153 @@
  */
 function voting_settings() {
   // form group: Colors
-  $group  = form_textfield(t('Background color for voting control'), 'voting_bgcolor', 
-    variable_get('voting_bgcolor', '0xffffff'), 8, 8);
-  $group .= form_textfield(t("Star 'on' fill color"), 'voting_on_fill', 
-    variable_get('voting_on_fill', '0x990000'), 8, 8);
-  $group .= form_textfield(t("Star 'on' border color"), 'voting_on_border', 
-    variable_get('voting_on_border', '0x330000'), 8, 8);
-  $group .= form_textfield(t("Star 'off' fill color"), 'voting_off_fill', 
-    variable_get('voting_off_fill', '0xcccccc'), 8, 8);
-  $group .= form_textfield(t("Star 'off' border color"), 'voting_off_border', 
-    variable_get('voting_off_border', '0x333333'), 8, 8);
-  $group .= form_textfield(t("Text color"), 'voting_txt_color', 
-    variable_get('voting_txt_color', '0x000000'), 8, 8);
-  $output .= form_group(t('Colors (0xffffff for white, 0x000000 for black, etc.)'), $group);
-  
-	// form group: Text Strings
-  $group  = form_textfield(t('Star 1'), 'voting_txt_vote1', 
-    variable_get('voting_txt_vote1', 'Awful'), 20, 20);
-  $group .= form_textfield(t('Star 2'), 'voting_txt_vote2', 
-    variable_get('voting_txt_vote2', 'Poor'), 20, 20);
-  $group .= form_textfield(t('Star 3'), 'voting_txt_vote3', 
-    variable_get('voting_txt_vote3', 'Average'), 20, 20);
-  $group .= form_textfield(t('Star 4'), 'voting_txt_vote4', 
-    variable_get('voting_txt_vote4', 'Good'), 20, 20);
-  $group .= form_textfield(t('Star 5'), 'voting_txt_vote5', 
-    variable_get('voting_txt_vote5', 'Excellent'), 20, 20);
-  $group .= form_textfield(t('Message shown BEFORE a user votes'), 'voting_txt_before_vote', 
-    variable_get('voting_txt_before_vote', 'Rate This:'), 20, 20);
-  $group .= form_textfield(t('Message shown AFTER a user votes'), 'voting_txt_after_vote', 
-    variable_get('voting_txt_after_vote', 'My Vote:'), 20, 20);
-  $group .= form_textfield(t('No permission to vote message'), 'voting_txt_login', 
-    variable_get('voting_txt_login', 'Please login or register to vote.'), 40, 40);
-  $output .= form_group(t('Text Messages (Leave blank for defaults)'), $group);
-  
-	// form group: Other
-	$group = form_radios(t('Voting controls on nodes'), 'voting_location', 
-	  variable_get('voting_location', 1), array(t('Display above the node'), t('Display below the node'), t('Do not display')), 
-		t('Position of the voting control.  Select "Do not display" if you are calling the voting module function directly from your theme and/or module code.'));
-	$group .= form_textfield(t("Voting IP timeout (in seconds)"), 'voting_ip_timeout', 
-    variable_get('voting_ip_timeout', 3600), 8, 8, 
-		t('Controls if and how often users with the same IP address can vote for the same thing.  Set it to 0 to disable this feature.'));
-		
-	$output .= form_group(t('Other'), $group);
-	
-  return $output;
+  $form['colors'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Colors (0xffffff for white, 0x000000 for black, etc.)'),
+  );
+  
+  $form['colors']['voting_bgcolor'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Background color for voting control'),
+    '#default_value' => variable_get('voting_bgcolor', '0xffffff'),
+    '#size' => 8,
+    '#maxlength' => 8,
+  );
+  
+  $form['colors']['voting_on_fill'] = array(
+    '#type' => 'textfield',
+    '#title' => t("Star 'on' fill color"),
+    '#default_value' => variable_get('voting_on_fill', '0x990000'),
+    '#size' => 8,
+    '#maxlength' => 8,
+  );
+  
+  $form['colors']['voting_on_border'] = array(
+    '#type' => 'textfield',
+    '#title' => t("Star 'on' border color"),
+    '#default_value' => variable_get('voting_on_border', '0x330000'),
+    '#size' => 8,
+    '#maxlength' => 8,
+  );
+  
+  $form['colors']['voting_off_fill'] = array(
+    '#type' => 'textfield',
+    '#title' => t("Star 'off' fill color"),
+    '#default_value' => variable_get('voting_off_fill', '0xcccccc'),
+    '#size' => 8,
+    '#maxlength' => 8,
+  );
+  
+  $form['colors']['voting_off_border'] = array(
+    '#type' => 'textfield',
+    '#title' => t("Star 'off' border color"),
+    '#default_value' => variable_get('voting_off_border', '0x333333'),
+    '#size' => 8,
+    '#maxlength' => 8,
+  );
+
+  $form['colors']['voting_txt_color'] = array(
+    '#type' => 'textfield',
+    '#title' => t("Text color"),
+    '#default_value' => variable_get('voting_txt_color', '0x000000'),
+    '#size' => 8,
+    '#maxlength' => 8,
+  );
+
+  // form group: Text Strings
+  $form['text'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Text Messages (Leave blank for defaults)'),
+  );
+  
+  $form['text']['voting_txt_vote1'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Star 1'),
+    '#default_value' => variable_get('voting_txt_vote1', 'Awful'),
+    '#size' => 20,
+    '#maxlength' => 20,
+  );
+  
+  $form['text']['voting_txt_vote2'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Star 2'),
+    '#default_value' => variable_get('voting_txt_vote2', 'Poor'),
+    '#size' => 20,
+    '#maxlength' => 20,
+  );
+
+  $form['text']['voting_txt_vote3'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Star 3'),
+    '#default_value' => variable_get('voting_txt_vote3', 'Average'),
+    '#size' => 20,
+    '#maxlength' => 20,
+  );
+  
+  $form['text']['voting_txt_vote4'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Star 4'),
+    '#default_value' => variable_get('voting_txt_vote4', 'Good'),
+    '#size' => 20,
+    '#maxlength' => 20,
+  );
+  
+  $form['text']['voting_txt_vote5'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Star 5'),
+    '#default_value' => variable_get('voting_txt_vote5', 'Excellent'),
+    '#size' => 20,
+    '#maxlength' => 20,
+  );
+  
+  $form['text']['voting_txt_before_vote'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Message shown BEFORE a user votes'),
+    '#default_value' => variable_get('voting_txt_before_vote', 'Rate This:'),
+    '#size' => 20,
+    '#maxlength' => 20,
+  );
+  
+  $form['text']['voting_txt_after_vote'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Message shown AFTER a user votes'),
+    '#default_value' => variable_get('voting_txt_after_vote', 'My Vote:'),
+    '#size' => 20,
+    '#maxlength' => 20,
+  );
+  
+  $form['text']['voting_txt_login'] = array(
+    '#type' => 'textfield',
+    '#title' => t('No permission to vote message'),
+    '#default_value' => variable_get('voting_txt_login', 'Please login or register to vote.'),
+    '#size' => 40,
+    '#maxlength' => 40,
+  );
+    
+  // form group: Other
+  $form['other'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Other'),
+  );
+  
+  $form['other']['voting_location'] = array(
+    '#type' => 'radios',
+    '#title' => t('Voting controls on nodes'),
+    '#default_value' => variable_get('voting_location', 1),
+    '#options' => array(t('Display above the node'), t('Display below the node'), t('Do not display')),
+    '#description' => t('Position of the voting control.  Select "Do not display" if you are calling the voting module function directly from your theme and/or module code.'),
+  );
+  
+  $form['other']['voting_ip_timeout'] = array(
+    '#type' => 'textfield',
+    '#title' => t("Voting IP timeout (in seconds)"),
+    '#default_value' => variable_get('voting_ip_timeout', 3600),
+    '#size' => 8,
+    '#maxlength' => 8,
+    '#description' => t('Controls if and how often users with the same IP address can vote for the same thing.  Set it to 0 to disable this feature.'),
+  );
+  
+  return $form;
 }
 
 /**
@@ -90,8 +194,8 @@
  */
 function voting_get_vote($content_type, $content_id) {
   global $user;
-  
-	// my vote
+
+  // my vote
   if ($_COOKIE["vote_{$content_type}_{$content_id}"]) { // get user's vote from a cookie on their computer
     $voting_id = $_COOKIE["vote_{$content_type}_{$content_id}"];
     $result = db_query("SELECT * FROM {votes} WHERE voting_id=%d", $voting_id);
@@ -103,37 +207,37 @@
     $result = db_query("SELECT * FROM {votes} WHERE content_type='%s' AND content_id=%d AND hostname='%s' AND timestamp > %d", $content_type, $content_id, $_SERVER['REMOTE_ADDR'], time() - variable_get("voting_ip_timeout", 60 * 60));
     $vote = db_fetch_object($result);
   }
-  
-	// average vote
-	$result = db_query("SELECT SUM(vote)/COUNT(vote) AS avg_vote FROM {votes} WHERE content_type='%s' AND content_id=%d", $content_type, $content_id);
-	$vote->avg_vote = $result ? db_result($result, "avg_vote") : 0;
-	$vote->avg_vote = round($vote->avg_vote / 0.5) * 0.5; // rounds to nearest half
-	$vote->avg_vote = number_format($vote->avg_vote, 1); // fixes to 1 decimal place
-	
-	// number of votes
-	$result = db_query("SELECT COUNT(vote) FROM {votes} WHERE content_type='%s' AND content_id=%d", $content_type, $content_id);
-	$vote->num_votes = $result ? db_result($result, 0) : 0;
-	
+
+  // average vote
+  $result = db_query("SELECT SUM(vote)/COUNT(vote) AS avg_vote FROM {votes} WHERE content_type='%s' AND content_id=%d", $content_type, $content_id);
+  $vote->avg_vote = $result ? db_result($result, "avg_vote") : 0;
+  $vote->avg_vote = round($vote->avg_vote / 0.5) * 0.5; // rounds to nearest half
+  $vote->avg_vote = number_format($vote->avg_vote, 1); // fixes to 1 decimal place
+
+  // number of votes
+  $result = db_query("SELECT COUNT(vote) FROM {votes} WHERE content_type='%s' AND content_id=%d", $content_type, $content_id);
+  $vote->num_votes = $result ? db_result($result, 0) : 0;
+
   return $vote;
 }
 
 /**
- * This function is used with a Macromedia Flash based voting control to send and receive data in 
+ * This function is used with a Macromedia Flash based voting control to send and receive data in
  * one step.  First, Flash is passed the content_type and content_id from the page where it is used.
- * Then, Flash calls /voting/flash and sends the content_type and content_id using POST.  A vote is 
+ * Then, Flash calls /voting/flash and sends the content_type and content_id using POST.  A vote is
  * not passed, so this function will not insert a vote, but it will return the current voting information.
- * If a user votes (or changes their vote), this function is called again from Flash, this time with 
+ * If a user votes (or changes their vote), this function is called again from Flash, this time with
  * a vote.
- * 
+ *
  */
 function voting_flash() {
   global $user;
-  
+
   $content_type = $_POST['content_type'];
   $content_id = $_POST['content_id'];
   $new_vote = $_POST['vote'];
   $vote = voting_get_vote($content_type, $content_id); // get average vote, number of votes, and user's current vote (if any)
-	
+
   if ($new_vote) { // if a new vote is sent...
     if ($vote->voting_id) { // ...and the user has already voted
       db_query("UPDATE {votes} SET vote=%d, timestamp=%d, hostname='%s' WHERE voting_id=%d", $new_vote, time(), $_SERVER['REMOTE_ADDR'], $vote->voting_id);
@@ -142,13 +246,13 @@
       $result = db_query("SELECT MAX(voting_id) FROM {votes}");
       $voting_id = $result ? db_result($result, 0) : 0;
       $voting_id++;
-      db_query("INSERT INTO {votes} (voting_id, content_type, content_id, vote, uid, timestamp, hostname) VALUES (%d, '%s', %d, %d, %d, %d, '%s')", 
+      db_query("INSERT INTO {votes} (voting_id, content_type, content_id, vote, uid, timestamp, hostname) VALUES (%d, '%s', %d, %d, %d, %d, '%s')",
         $voting_id, $content_type, $content_id, $new_vote, $user->uid, time(), $_SERVER['REMOTE_ADDR']);
       setcookie ("vote_{$content_type}_{$content_id}", $voting_id, time()+60*60*24*30); // expire in 30 days
     }
-		$vote = voting_get_vote($content_type, $content_id); // get new updated average vote and number of votes
+    $vote = voting_get_vote($content_type, $content_id); // get new updated average vote and number of votes
   }
-	
+
   // return the current vote info to flash
   $vote->vote = ($vote->vote) ? $vote->vote : 0;
   $vote->avg_vote = ($vote->avg_vote) ? $vote->avg_vote : 0;
@@ -181,18 +285,18 @@
  */
 function theme_voting_control_flash($content_type, $content_id, $attributes = array()) {
   global $user;
-  
+
   // required variables
   $url = urlencode('voting/flash'); // callback URL that retrieves voting info and process votes
-	
+
   // optional: user_access() dependent variables
   if (user_access('vote on content') && user_access('show average without voting')) {
     $mode = 'show_avg_first';
   } elseif (user_access('show average without voting')) {
     $mode = 'show_avg_only';
   }
-	
-	// optional: variables set from administer/settings/voting
+
+  // optional: variables set from administer/settings/voting
   $star_on_fill = variable_get('voting_on_fill', '0x990000');
   $star_on_border = variable_get('voting_on_border', '0x330000');
   $star_off_fill = variable_get('voting_off_fill', '0xcccccc');
@@ -204,26 +308,26 @@
   $txt_vote4 = variable_get('voting_txt_vote4', 'Good');
   $txt_vote5 = variable_get('voting_txt_vote5', 'Excellent');
   $txt_login = urlencode(variable_get('voting_txt_login', 'Please login or register to vote.'));
-	
-	// optional: certain variables can be overridden on individual voting controls
-	//   ex: $output .= voting_control_generic('pagevote', $node->nid, array('prompt' => 'Do you like it?', 'confirmation' => 'Vote saved!', 'bgcolor' => '0xffffff'));
+
+  // optional: certain variables can be overridden on individual voting controls
+  //   ex: $output .= voting_control_generic('pagevote', $node->nid, array('prompt' => 'Do you like it?', 'confirmation' => 'Vote saved!', 'bgcolor' => '0xffffff'));
   $txt_before_vote = urlencode(($attributes['prompt']) ? $attributes['prompt'] : variable_get('voting_txt_before_vote', 'Rate This:'));
   $txt_after_vote = urlencode(($attributes['confirmation']) ? $attributes['confirmation'] : variable_get('voting_txt_after_vote', 'My Vote:'));
-	$bgcolor = ($attributes['bgcolor']) ? $attributes['bgcolor'] : variable_get('voting_bgcolor', '0xffffff');
-	
+  $bgcolor = ($attributes['bgcolor']) ? $attributes['bgcolor'] : variable_get('voting_bgcolor', '0xffffff');
+
   // make optional variables into a really long querystring
   $optional_vars = "&mode=$mode&bgcolor=$bgcolor&star_on_fill=$star_on_fill&star_on_border=$star_on_border";
   $optional_vars .= "&star_off_fill=$star_off_fill&star_off_border=$star_off_border&txt_color=$txt_color";
   $optional_vars .= "&txt_vote1=$txt_vote1&txt_vote2=$txt_vote2&txt_vote3=$txt_vote3&txt_vote4=$txt_vote4&txt_vote5=$txt_vote5";
   $optional_vars .= "&txt_login=$txt_login&txt_before_vote=$txt_before_vote&txt_after_vote=$txt_after_vote";
-  
-	// create the Flash filename, including the required variables and optional querystring
-	$filename = drupal_get_path('module', 'voting') . "/voting.swf?content_type=$content_type&content_id=$content_id&url=$url" . $optional_vars;
-  
-	// create the HTML to put the Flash object on the page
-	//
-	// NOTE: The object is nested in a table for CSS styling.  It does 
-	// not seem to work correctly in Firefox when a DIV is used instead.
+
+  // create the Flash filename, including the required variables and optional querystring
+  $filename = base_path() . drupal_get_path('module', 'voting') . "/voting.swf?content_type=$content_type&content_id=$content_id&url=$url" . $optional_vars;
+
+  // create the HTML to put the Flash object on the page
+  //
+  // NOTE: The object is nested in a table for CSS styling.  It does
+  // not seem to work correctly in Firefox when a DIV is used instead.
   $output .= "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=\"voting\"><tr><td>\n";
   $output .= '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
    codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"
@@ -234,7 +338,7 @@
    type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>' . "\n";
   $output .= "</object>\n";
   $output .= "</td></tr></table>\n";
-  
+
   return $output;
 }
 
@@ -246,25 +350,15 @@
   switch ($op) {
     case 'view':
       if (!$teaser) {
-				switch (variable_get('voting_location', 1)) {
-					case 0: // display above the node
-						$node->body = voting_control_node($node, $teaser, $page) . $node->body;
-						break;
-					case 1: // display below the node
-						$node->body .= voting_control_node($node, $teaser, $page);
-						break;
-					case 2: // do not display
-				}
-      }
-      break;
-    case 'settings': // default workflow settings (administer/content/configure/content types)
-      return form_radios(t('Voting'), 'voting_'. $node->type, variable_get('voting_'. $node->type, 0), array(t('Disabled'), t('Enabled')));
-    case 'form admin': // editing a node
-      if (user_access('administer nodes')) {
-        $selected = isset($node->voting) ? $node->voting : variable_get('voting_' . $node->type, 0);
-        $output = form_radios('', 'voting', $selected, array(t('Disabled'), t('Enabled')));
-				//return form_group_collapsible(t('Voting options'), $output, TRUE); // for Drupal 4.7+
-        return form_group(t('Voting options'), $output); // for Drupal 4.6 and before
+        switch (variable_get('voting_location', 1)) {
+          case 0: // display above the node
+            $node->body = voting_control_node($node, $teaser, $page) . $node->body;
+            break;
+          case 1: // display below the node
+            $node->body .= voting_control_node($node, $teaser, $page);
+            break;
+          case 2: // do not display
+        }
       }
       break;
     case 'load':
@@ -272,7 +366,7 @@
       if ($voting = db_fetch_object($result)) {
         $node->voting = $voting->voting;
       } else {
-        $node->voting = variable_get("voting_$node->type", 0);
+        $node->voting = variable_get('voting_'. $node->type, 0);
       }
       if ($teaser) {
         $node->voting = 0;
@@ -281,10 +375,10 @@
     case 'validate':
       if (!user_access('administer nodes')) {
         // Force default (for this content type) for normal users:
-        $node->voting = variable_get('voting_' . $node->type, 0);
+        //$node->voting = variable_get('voting_' . $node->type, 0);
       }
-			voting_filter_validate($node);
-      break; 
+      voting_filter_validate($node);
+      break;
     case 'update':
       $result = db_query("SELECT * FROM {node_voting} WHERE nid = %d", $node->nid);
       if ($row = db_fetch_object($result)) { // if the voting on/off setting is already in the database
@@ -303,14 +397,41 @@
   }
 }
 
+function voting_form_alter($form_id, &$form) {
+  // default workflow settings (administer/content/configure/content types)
+  if (isset($form['type']) && $form['type']['#value'] .'_node_settings' == $form_id) {
+    $form['workflow']['voting_'. $form['type']['#value']] = array(
+      '#type' => 'radios',
+      '#title' => t('Voting'),
+      '#default_value' => variable_get('voting_options_'. $form['type']['#value'], 0),
+      '#options' => array(t('Disabled'), t('Enabled')),
+    );
+  }
+  // editing a node
+  if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
+    $node = $form['#node'];
+    if (user_access('administer nodes')) {
+      $form['voting_options'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Voting options'),
+      );
+      $form['voting_options']['voting'] = array(
+        '#type' => 'radios',
+        '#default_value' => isset($node->voting) ? $node->voting : variable_get('voting_'. $form['type']['#value'], 0),
+        '#options' => array(t('Disabled'), t('Enabled')),
+      );
+    }
+  }
+}
+
 /** ---------------------------------------------------------------------------------------------------
  * Voting Filter
  *
- * This section implements the hook_filter() and hook_filter_tips() to allow uses to add voting controls 
- * to their posts.  The format is [voting|type=artwork|prompt=Rate my artwork:|confirmation=Thanks for voting!] 
+ * This section implements the hook_filter() and hook_filter_tips() to allow uses to add voting controls
+ * to their posts.  The format is [voting|type=artwork|prompt=Rate my artwork:|confirmation=Thanks for voting!]
  * The voting filter works great with the tinyMCE WYSIWYG editor and the drupalvoting plugin.
  * ---------------------------------------------------------------------------------------------------- */
- 
+
 /**
  * Implementation of hook_filter().
  */
@@ -323,9 +444,9 @@
       return t('Add voting to your posts.');
 
     case 'process':
-			// get all instances of the filter and send each one to the voting_filter_process() function
-			$regex_tags = "/\[voting\|([^\]]+)\]/";
-			$text = preg_replace_callback($regex_tags, "voting_filter_process", $text);
+      // get all instances of the filter and send each one to the voting_filter_process() function
+      $regex_tags = "/\[voting\|([^\]]+)\]/";
+      $text = preg_replace_callback($regex_tags, "voting_filter_process", $text);
       return $text;
 
     default:
@@ -337,16 +458,16 @@
  * Implementation of hook_filter_tips().
  */
 function voting_filter_tips($delta, $format, $long = false) {
-	switch ($long) {
-		case 0:
-			return t('Voting controls can be added to this post.');
-		case 1:
-			return t('
-				<h4>Adding Voting Controls</h4>
-				<p>You can let people vote on your post, or things in your post, just by adding a carefully formatted tag in your post.
-				The tag should look like this: <br />[voting|type=artwork|prompt=Rate my artwork:|confirmation=Thanks for voting!] 
-				The prompt and confirmation are optional.</p>');
-	}
+  switch ($long) {
+    case 0:
+      return t('Voting controls can be added to this post.');
+    case 1:
+      return t('
+        <h4>Adding Voting Controls</h4>
+        <p>You can let people vote on your post, or things in your post, just by adding a carefully formatted tag in your post.
+        The tag should look like this: <br />[voting|type=artwork|prompt=Rate my artwork:|confirmation=Thanks for voting!]
+        The prompt and confirmation are optional.</p>');
+  }
 }
 
 /**
@@ -355,38 +476,107 @@
  * $match[1] is the attributes in the form "type=node|id=123|prompt=Rate This:|confirmation=My Vote:"
  */
 function voting_filter_process($match) {
-	$regex_attributes = "/([a-zA-Z]*)=([^\|]+)/";
-	preg_match_all($regex_attributes, $match[1], $attributes, PREG_SET_ORDER);
-	foreach ($attributes as $attribute) {
-		$atts[$attribute[1]] = $attribute[2];
-	}
-	return voting_control_generic($atts['type'], $atts['id'], $atts);
+  $regex_attributes = "/([a-zA-Z]*)=([^\|]+)/";
+  preg_match_all($regex_attributes, $match[1], $attributes, PREG_SET_ORDER);
+  foreach ($attributes as $attribute) {
+    $atts[$attribute[1]] = $attribute[2];
+  }
+  return voting_control_generic($atts['type'], $atts['id'], $atts);
 }
 
 /**
  * Called by voting_nodeapi, this function adds an ID (the nid) to the voting filter if it has been left off
  */
 function voting_filter_validate(&$node) {
-	// get all instances of the voting filter
-	$regex_tags = "/\[voting\|([^\]]+)\]/";
-	preg_match_all($regex_tags, $node->body, $matches, PREG_SET_ORDER);
-		
-	foreach ($matches as $match) {
-		$orig_filter_str = $match[0];
-		if (!preg_match("/id=[0-9]+/", $orig_filter_str)) {
-			if ($node->nid) {
-				$voting_nid = $node->nid;
-			} else {
-				// on a new post the NID hasn't been assigned yet and we can't call
-			  // db_next_id() yet becuase it will mess up the sequence for the node_save().
-				// my current solution is to use two modified lines from db_next_id() to get the 
-				// next nid without incrementing it.
-				$name = db_prefix_tables('{node}_nid');
-				$voting_nid = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", $name)) + 1;
-			}
-			$new_filter_str = str_replace('[voting', '[voting|id=' . $voting_nid, $orig_filter_str);
-			$node->body = str_replace($orig_filter_str, $new_filter_str, $node->body);
-		}
-	}
+  // get all instances of the voting filter
+  $regex_tags = "/\[voting\|([^\]]+)\]/";
+  preg_match_all($regex_tags, $node->body, $matches, PREG_SET_ORDER);
+
+  foreach ($matches as $match) {
+    $orig_filter_str = $match[0];
+    if (!preg_match("/id=[0-9]+/", $orig_filter_str)) {
+      if ($node->nid) {
+        $voting_nid = $node->nid;
+      } else {
+        // on a new post the NID hasn't been assigned yet and we can't call
+        // db_next_id() yet becuase it will mess up the sequence for the node_save().
+        // my current solution is to use two modified lines from db_next_id() to get the
+        // next nid without incrementing it.
+        $name = db_prefix_tables('{node}_nid');
+        $voting_nid = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", $name)) + 1;
+      }
+      $new_filter_str = str_replace('[voting', '[voting|id=' . $voting_nid, $orig_filter_str);
+      $node->body = str_replace($orig_filter_str, $new_filter_str, $node->body);
+    }
+  }
+}
+
+/**
+  * Get ids of top rated content
+  */
+function voting_top_rated($content_type = 'node', $life = 30) {
+  // this information should probably be cached somehow
+  // and probably updated with a cron job
+
+  if ($content_type == 'node') {
+    $birth = strtotime("-$life days");
+    $result = db_query('SELECT v.content_id AS id, AVG(v.vote) AS average FROM {votes} v INNER JOIN {node} n ON n.nid = v.content_id WHERE v.content_type="node" AND n.created > %d GROUP BY id ORDER BY average DESC', $birth);
+  }
+  else {
+    $result = db_query('SELECT content_id AS id, AVG(vote) AS average FROM {votes} WHERE content_type="%s" GROUP BY id ORDER BY average DESC', $content_type);
+  }
+  while($item = db_fetch_object($result)){
+    $return[] = $item->id;
+  }
+  return (array)$return;
+}
+
+function voting_block($op = 'list', $delta = 0, $edit = array()) {
+  if ($op == 'list') {
+    $blocks[0]['info'] = t('Top Rated Nodes');
+    return $blocks;
+  }
+  else if ($op == 'configure' && $delta == 0) {
+    $form['items'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Number of items'),
+      '#default_value' => variable_get('voting_block_items', 10),
+      '#size' => 5,
+      '#maxlength' => 10,
+    );
+    $form['days'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Within last x days'),
+      '#default_value' => variable_get('voting_block_days', 30),
+      '#size' => 5,
+      '#maxlength' => 10,
+    );
+    
+    return $form;
+  }
+  else if ($op == 'save' && $delta == 0) {
+    variable_set('voting_block_items', $edit['items']);
+    variable_set('voting_block_days', $edit['days']);
+  }
+  else if ($op == 'view') {
+    switch($delta) {
+      case 0:
+        $block['subject'] = t('Top Rated Items');
+        $block['content'] = voting_top_nodes('node', variable_get('voting_block_days', 30));
+        break;
+    }
+    return $block;
+  }
+}
+
+function voting_top_nodes() {
+  $nids = voting_top_rated();
+  foreach ($nids as $nid) {
+    $node = node_load($nid);
+    $list .= '<li>'.l($node->title, 'node/'.$node->nid).'</li>';
+  }
+  $output = "<ol>";
+  $output .= $list;
+  $output .= "</ol>";
+  return $output;
 }
-?>
\ No newline at end of file
