<?php
/*
Plugin Name: Count comments
Plugin URI: http://www.stilglog.com/wordpress-plugins/count-comments
Description: Count comments 
Author: Martijn van der Kwast
Version: 0.4
Author URI: http://www.stilglog.com

Count the number of comments by a commenter.

## Usage:

- To display the count to a comment display add this in the comment loop 
  ($comment must be globally defined).

  <?php cc_comment_count(); ?>

  Example in comments.php in the Kubrick theme:
  Find

  <cite><?php comment_author_link</cite> Says:

  and add insert this in that line:

  <?php cc_comment_count('','(1)','(%c)'); ?>


- To add the count to a summary page outside the loop (a user information
  page for instance), add this:

  <?php cc_comment_count_email($an_email); ?>

- Display a list commenters and the number of comments they posted:

  <?php cc_comment_stats(); ?>

  The same thing but in an HTML list:

  <ul>
  <?php cc_comment_stats(0, '<li>%a: %c</li>' ); ?>
  </ul>

  Or in the 5 top commenters in a table:

  <table>
	  <?php cc_comment_stats(5, '<tr><td>%a</td><td>%c</td></tr>'); ?>
  </table>


	  

## Reference:

function cc_get_comment_count($comment)  
 * Return number of comments made by the author of this comment.
 * parameters:
 * $comment: current comment structure.

function cc_comment_count($zero='', $one='1 comment', $more='%c comments')
 * Display the number of comments made by the author of the current comment in the comment loop.
 * parameters:
 * $comment: current comment structure.
 * $zero, $one, $more: %c get replaced with the number of comments.

function cc_get_count_comments_email()  
 * Get the number of comments made by someone with this email, outside the comment context. 
 * parameters:
 * $email: email of user to count comments for

function cc_comment_count_email($email, $zero='', $one='1 comment', $more='%c comments')
 * Display the number of comments made by someone, outside the comment context.
 * parameters:
 * $zero, $one, $more: how to display comments, %c gets replaced with the count

function cc_comment_stats($number=0, $format='%a (%e): %c<br/>')
 * Display a summary table of commenters and the number of comments they made,
 * sorted by number of comments, the most prolific commenter first.
 * parameters:
 * $format: 
 *   %a is replaced with the author's name
 *   %e is replaced with his email
 *   %c is replaced with the number of comments
 * $number: 
 *   number of lines to display, 0 means display all.


## Remarks: 
Email addresses are used to recognize commenters.

The results are cached to avoid using too many queries to increase 
performance. 

If the number of comments gets really big, it would be better to 
cache the counts in the database instead of calculating them.


## Changes:

0.4: don't hardcode table prefix

0.3: Octobre 13th 2005
     - fixed counting for an email address (not in a comment nor 
	   a post context).

0.2: Septembre 18th 2005
     - who knows what changed ;)

0.1: original release


*/

$_cc_cache=array();

function _cc_precache_posts_counts($post_ID)
{
	global $wpdb;
	global $_cc_cache;

	$post_ID=intval($post_ID);
	if (!$post_ID) {
		return;
	}

	// get all commenters for current post
	$q = "SELECT DISTINCT comment_author_email FROM $wpdb->comments " .
	     "WHERE comment_post_ID = $post_ID AND comment_author_email <> '' ";

	$authors = $wpdb->get_col($q);
	if (!$authors) {
		return;
	}

	$aq='';
	foreach ($authors as $author) {
		$aq.="'".$wpdb->escape($author)."', ";
	}
	$aq=substr($aq, 0, -2);
	
	$q = "SELECT comment_author_email, COUNT(*) AS count FROM $wpdb->comments " .
	     "WHERE comment_author_email in ( $aq ) " .
		 "GROUP BY comment_author_email";

	$rows = $wpdb->get_results($q);

	// save results
	foreach ($rows as $row) {
		$_cc_cache[$row->comment_author_email] = $row->count;
	}
}

function _cc_precache_all_counts()
{
	global $wpdb;
	global $_cc_cache;

	// get global comment counts for all mentionned authors
	$q = "SELECT comment_author_email, COUNT(*) AS count FROM $wpdb->comments " .
		 "WHERE comment_author_email <> '' ".
		 "GROUP BY comment_author_email";

	$rows = $wpdb->get_results($q);

	// save results
	foreach ($rows as $row) {
		$_cc_cache[$row->comment_author_email] = $row->count;
	}
}

/*
 * Return number of comments made by the author of this comment.
 * parameters:
 * $comment: current comment structure.
 */
function cc_get_comment_count($comment)
{
	global $_cc_cache;

	if (empty($comment->comment_author_email)) {
		return 0;
	}
	
	if (!isset($_cc_cache[$comment->comment_author_email])) {
		_cc_precache_posts_counts($comment->comment_post_ID);
	}

	return $_cc_cache[$comment->comment_author_email];
}

/*
 * Display the number of comments made by the author of the current comment in the comment loop.
 * parameters:
 * $comment: current comment structure.
 * $zero, $one, $more: %c get replaced with the number of comments.
 */
function cc_comment_count($zero='', $one='1 comment', $more='%c comments')
{
	global $comment;
	
	$num = cc_get_comment_count($comment);

	if ($num == 0) {
		print str_replace('%c', $num, $zero);
	} else if ($num == 1) {
		print str_replace('%c', $num, $one);
	} else if( $num > 1) {
		print str_replace('%c', $num, $more);
	}
}

/*
 * Get the number of comments made by someone with this email, outside the comment context. 
 * parameters:
 * $email: email of user to count comments for
 */
function cc_get_count_comments_email($email)
{
	global $_cc_cache;
 
	if (!isset($_cc_cache[$email])) {
		_cc_precache_all_counts();
	}

	return $_cc_cache[$email];
}

/*
 * Display the number of comments made by someone, outside the comment context.
 * parameters:
 * $zero, $one, $more: how to display comments, %c gets replaced with the count
 */
function cc_comment_count_email($email, $zero='', $one='1 comment', $more='%c comments')
{
	$num=cc_get_count_comments_email($email);
	if ($num < 0) {
		print str_replace('%c', $num, $invalid);
	} else if ($num == 1) {
		print str_replace('%c', $num, $singular);
	} else {
		print str_replace('%c', $num, $plural);
	}
}


/*
 * Display a summary table of commenters and the number of comments they made,
 * sorted by number of comments, the most prolific commenter first.
 * parameters:
 * $number: 
 *   number of lines to display, 0 means display all.
 * $format: 
 *   %a is replaced with the author's name
 *   %e is replaced with his email
 *   %c is replaced with the number of comments
 */
function cc_comment_stats($number, $format='%a (%e): %c<br/>')
{
	global $wpdb;
	
	$q = "SELECT comment_author_email, COUNT(*) count FROM $wpdb->comments " .
		 "WHERE comment_author_email <> '' ".
		 "GROUP BY comment_author_email ".
		 "ORDER BY count DESC ";

	// this is not standard SQL as we group by comment_author_email, but select
	// comment_author, comment_author_email.
	$q = <<<SQL
		SELECT 
		comment_author
		,comment_author_email 
		,COUNT(*) AS count 
		FROM $wpdb->comments
		WHERE comment_author_email <> ''
		GROUP BY comment_author_email
		ORDER BY count DESC
SQL;

	$number=intval($number);
	if ($number) {
		$q.=" LIMIT $number";
	}

	$rows = $wpdb->get_results($q);

	foreach($rows as $row) {
		print str_replace(array('%a', '%e', '%c'), array($row->comment_author, $row->comment_author_email, $row->count), $format);
	}
}
 
?>
