All pastes #66604 Raw Edit

headzoo

public text v1 · immutable
#66604 ·published 2006-06-17 17:51 UTC
rendered paste body
<?php
/**
 * Plugin Name: Rate and Comment
 * Plugin URI: http://www.headzoo.com/rateandcomment
 * Author: Sean Hickey
 * Author URI: http://www.headzoo.com
 * Version: 1.0
 * Description: Rate a post only when a comment is left
 */
 
define('RAC_PATH', ABSPATH . '/wp-content/plugins/rate_comment');
define('RAC_URL', get_bloginfo('url') . '/wp-content/plugins/rate_comment');

/**
 * Rate and Comment class
 *
 * @author	Sean Hickey
 * @version	1.0
 * @todo
 */
class RAC {

	/**
	 * The $wpdb object.
	 * @var obj
	 */
	var $wpdb;
	
	/**
	 * The database table prefix.
	 * @var string
	 */
	var $table_prefix;
	
	/**
	 * The full path to the plugin directory.
	 * @var string
	 */
	var $path;
	
	/**
	 * The URL to the plugin directory.
	 * @var string
	 */
	var $url;
	
	/**
	 * Class constructor
	 *
	 * @param	obj		$wpdb		The $wpdb object
	 * @param	string	$table_prefix	The database table prefix
	 * @param	string	$path		The full path to the plugin directory
	 * @param	string	$url			The URL to the plugin directory
	 * @return	void
	 */
	function RAC(&$wpdb, $table_prefix, $path, $url) {
		$this->wpdb = & $wpdb;
		$this->table_prefix = $table_prefix;
		$this->path = $path;
		$this->url = $url;
		$this->wpdb->comment_votes = $table_prefix . 'comment_votes';
		
		add_action('wp_head', array(&$this, 'wpHead'));
		add_action('comment_form', array(&$this, 'ratingComment'));
		add_action('activate_rate_comment/rate_comment.php', array(&$this, 'install'));
		add_action('comment_post', array(&$this, 'castVote'));
		add_action('delete_comment', array(&$this, 'deleteComment'));
	}
	
	/**
	 * Remove vote when a comment is deleted
	 *
	 * When a comment is deleted, this method checks to see if a vote was made with that
	 * comment.  If so, the vote is removed, and the average rating for that post is
	 * changed, so that it was like the vote was never cast in the first place.  Returns
	 * the comment ID.
	 *
	 * @param	int	$commentID	The ID for the comment being deleted
	 * @return	int
	 */
	function deleteComment($commentID) {
	
		$commentID = (int) $commentID;
		$comment = $this->wpdb->get_results("SELECT ID, post_ID FROM `{$this->wpdb->comment_votes}` WHERE `comment_ID` = $commentID", ARRAY_A);
		if (empty($comment)) {
			return $commentID;
		}
		
		$commentID = (int) $comment[0]['ID'];
		$commentPostID = (int) $comment[0]['post_ID'];
		
		$this->wpdb->query("DELETE FROM `{$this->wpdb->comment_votes}` WHERE ID = $commentID");
		$allPostComments = $this->wpdb->get_results("SELECT vote FROM `{$this->wpdb->comment_votes}` WHERE `post_ID` = $commentPostID", ARRAY_A);
		
		$totalVotes = count($allPostComments);
		$voteCount = 0;
		for ($i = 0; $i < $totalVotes; $i++) {
			$voteCount += $allPostComments[$i]['vote'];
		}
		
		$newAverage = round(($voteCount / $totalVotes), 1);
		$this->wpdb->query("UPDATE `{$this->wpdb->posts}` SET `total_vote` = `total_vote` - 1, `post_current_vote` = $newAverage");
		return $commentID;
	}
	
	/**
	 * Add JS/CSS to document head
	 *
	 * Adds the required JavaScript and CSS stylesheet to the document's
	 * head.
	 *
	 * @return	void
	 */
	function wpHead() {
		if (is_single()) {
			?>
			<script type="text/javascript">
			var siteURL = '<?php echo $this->url; ?>';
			</script>
			<script type="text/javascript" src="<?php echo $this->url; ?>/head.js"></script>
			<link rel="stylesheet" type="text/css" href="<?php echo $this->url; ?>/head.css" />
			<?php
		}
	}
	
	/**
	 * Remove the add to comment form action
	 *
	 * If the rating_comment() function is used, then don't autoinsert the rating stars in
	 * the comment form.
	 *
	 * @return	void
	 */
	function functionCalled() {
		remove_action('comment_form', array(&$this, 'ratingComment'));
	}
	
	/**
	 * Writes a vote to the database
	 *
	 * After the comment form has been submitted, this method will check to see
	 * if a vote has been cast, and then records that vote to the database. Always
	 * returns TRUE.
	 *
	 * @return	bool
	 */
	function castVote($commentID) {
	
		$commentID = (int) $commentID;
		if (empty($_POST['newvote'])) {
			return true;
		}
		
		$postID = (int) $_POST['newvotepostid'];
		$ipAddress = $this->wpdb->escape($_SERVER['REMOTE_ADDR']);
		if ($this->hasVotedAlready($postID)) {
			return true;
		}
		
		$totalVotes = $this->wpdb->get_var("SELECT total_vote FROM `{$this->wpdb->posts}` WHERE `ID` = {$postID}");
		$currentVote = $this->wpdb->get_var("SELECT post_current_vote FROM `{$this->wpdb->posts}` WHERE `ID` = {$postID}");
		if (empty($totalVotes)) {
			$totalVotes = 0;
		}
		if (empty($currentVote)) {
			$currentVote = 0;
		}
		
		$currentVote += (int) $_POST['newvote'];
		$d = $currentVote;
		$totalVotes++;
		$currentVote = round($currentVote / $totalVotes, 1);
		
		$this->wpdb->query("INSERT INTO `{$this->wpdb->comment_votes}` VALUES (null, '$ipAddress', '{$_POST['newvote']}', {$postID}, {$commentID})");
		$this->wpdb->query("UPDATE `{$this->wpdb->posts}` SET `total_vote` = $totalVotes, `post_current_vote` = $currentVote WHERE ID = {$postID}");
		$this->wpdb->query("UPDATE `{$this->wpdb->comments}` SET `post_current_vote` = $d WHERE `comment_post_ID` = {$postID}");
		
		return true;
	}
	
	/**
	 * Method that displays rating form
	 *
	 * This method displays the rating stars.
	 *
	 * @param	int		$postID		The ID of the post
	 * @param	string	$before		String to display before the stars
	 * @param	string	$after		String to display after the stars
	 * @return	void
	 */
	function ratingComment($postID = null, $before = null, $after = null) {
		global $post;
		$currentVote = $this->getCurrentVote($post->ID);

		$stars = $this->getStars($currentVote, $this->hasVotedAlready($post->ID));
		echo $before . '<span id="rating_star_group">' . $stars . '</span> <input type="hidden" id="rating_comment" name="newvote" value="0" /><input type="hidden" name="newvotepostid" value="' . $post->ID . '" />' . $after;
	}

	/**
	 * Create star HTML
	 *
	 * Generates the rating star HTML.  Adds the JavaScript and CSS to the stars if
	 * the person hasn't voted already.
	 *
	 * @param	int		$vote		The current vote for the post
	 * @param	int		$hasVoted	0 if the person hasn't voted yet, anything else if they have
	 * @return	string
	 */
	function getStars($vote, $hasVoted) {
		$html = '';
		$starOn = $this->url . '/star_on.png';
		$starOff = $this->url . '/star_off.png';
		$starHalf = $this->url . '/star_half.png';
		
		if (!$hasVoted) {
			$js = ' onclick="ratingComment(%s);" ';
			$class = 'rating_star';
		} else {
			$js = '';
			$class = 'rated_star';
		}
		
		switch ($vote) {
			case 0:
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '5');
				break;
			case .5:
				$html .= sprintf("<img class=\"%s\" src=\"$starHalf\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '5');
				break;
			case 1:
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '5');
				break;
			case 1.5:
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starHalf\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '5');
				break;
			case 2:
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '5');
				break;
			case 2.5:
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starHalf\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '5');
				break;
			case 3:
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '5');
				break;
			case 3.5:
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starHalf\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '5');
				break;
			case 4:
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOff\" $js alt=\"Star\" />", $class, '5');
				break;
			case 4.5:
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starHalf\" $js alt=\"Star\" />", $class, '5');
				break;
			case 5:
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '1');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '2');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '3');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '4');
				$html .= sprintf("<img class=\"%s\" src=\"$starOn\" $js alt=\"Star\" />", $class, '5');
				break;
		}
		return $html;
	}
	
	/**
	 * Get vote for post ID
	 *
	 * Returns the current vote for the given post ID.
	 *
	 * @param	int	$postID	The ID for the post
	 * @return	float
	 */
	function getCurrentVote($postID) {
		$postID = (int) $postID;
		$currentVote = $this->wpdb->get_var("SELECT post_current_vote FROM `{$this->wpdb->posts}` WHERE `ID` = {$postID}");
		if (empty($currentVote)) {
			$currentVote = 0;
		}
		return $currentVote;
	}
	
	/**
	 * Returns the number of votes for a post
	 *
	 * Given the post ID, returns the number of times that post has received vots.
	 *
	 * @return	int
	 */
	function getTotalVotes($postID) {
		$postID = (int) $postID;
		$totalVotes = $this->wpdb->get_var("SELECT total_vote FROM `{$this->wpdb->posts}` WHERE `ID` = $postID");
		if (empty($totalVotes)) {
			$totalVotes = 0;
		}
		return $totalVotes;
	}
	
	/**
	 * Checks if the person has voted already
	 *
	 * Returns 0 if the person hasn't voted already for this post ID, or anything else if
	 * they have voted.
	 *
	 * @param	int	$postID	The post ID
	 * @return	int
	 */
	function hasVotedAlready($postID) {
		$ipAddress = $this->wpdb->escape($_SERVER['REMOTE_ADDR']);
		return $this->wpdb->get_var("SELECT ID FROM `{$this->wpdb->comment_votes}` WHERE `ip` = '$ipAddress' AND `post_ID` = $postID");
	}
	
	/**
	 * Install plugin method
	 *
	 * Method that is run when the plugin is activated.  If the tables for the
	 * plugin hasn't already been created, they will be created.
	 *
	 * @return	void
	 */
	function install() {

		if($this->wpdb->get_var("show tables like '{$this->wpdb->comment_votes}'") != $this->wpdb->comment_votes) {
			$sql = "CREATE TABLE `{$this->wpdb->comment_votes}` (
			`ID` BIGINT NOT NULL AUTO_INCREMENT,
			`ip` VARCHAR( 15 ) NOT NULL ,
			`vote` FLOAT NOT NULL ,
			`post_ID` INT NOT NULL ,
			`comment_ID` BITINT NOT NULL,
			PRIMARY KEY ( `ID` )
			) TYPE = MYISAM ;";
			$this->wpdb->query($sql);
		
			$sql = "ALTER TABLE `{$this->wpdb->posts}` ADD `total_vote` BIGINT NOT NULL ,
			ADD `post_current_vote` FLOAT NOT NULL ;
			ALTER TABLE `{$this->wpdb->posts}` ADD INDEX ( `post_current_vote` );";
			$this->wpdb->query($sql);
			
			$sql = "ALTER TABLE `{$this->wpdb->comments}` ADD `post_current_vote` FLOAT NOT NULL ;
			ALTER TABLE `{$this->wpdb->comments}` ADD INDEX ( `post_current_vote` );";
			$this->wpdb->query($sql);
		}
	}
}

$rac = new RAC($wpdb, $table_prefix, RAC_PATH, RAC_URL);

/**
 * Wrapper class for $rac->ratingComment()
 *
 * @param	string	$before	String to display before stars
 * @param	string	$after	String to display after stars
 * @return	void
 */
function rating_comment($before = '', $after = '') {
	global $rac;
	$rac->functionCalled();
	$rac->ratingComment(null, $before, $after);
}

/**
 * Returns the rating for a post
 *
 * Returns the HTML rating stars for a post.
 *
 * @return	string
 */
function get_rating_comment() {
	ob_start();
	rating_comment();
	$contents = ob_get_contents();
	ob_end_clean();
	return $contents;
}

/**
 * Returns current rating for a post
 *
 * Returns the current rating for the given post ID.
 *
 * @return	float
 */
function get_current_vote($postID) {
	global $rac;
	return $rac->getCurrentVote($postID);
}

/**
 * Displays the current rating for a post
 *
 * Returns the current rating for a given post ID.  Text can be set to return if
 * the post has no votes.
 *
 * @param	int		$postID		The ID for the post
 * @param	string	$before		String to display before the current rating
 * @param	string	$after		String to display after the current rating
 * @param	string	$notRated	String to display if the post has no votes
 * @return	string
 */
function current_vote($postID, $before = '', $after = '', $notRated = 'Not rated yet') {
	$currVote = get_post_current_vote($postID);
	if ($currVote == 0) {
		$currVote = $notRated;
	}
	echo $before . $currVote . $after;
}

/**
 * Returns the number of votes for a post
 *
 * Returns the number of times votes have been cast for the given post
 * ID.
 *
 * @return int
 */
function get_totalVotes($postID) {
	global $rac;
	return $rac->getTotalVotes($postID);
}

/**
 * Displays the total votes for a post
 *
 * Given a post ID, displays the number of times votes have been cast for that
 * post.  Text can be set to return if there are no votes.
 * @param	int		$postID		The ID for the post
 * @param	string	$before		String to display before the total votes
 * @param	string	$after		String to display after the total votes
 * @param	string	$notRated	String to display if the post has no votes
 * @return	string
 */
function totalVotes($postID, $before = '', $after = '', $noVotes = 'No votes') {
	$totalVotes = get_totalVotes($postID);
	if ($totalVotes == 0) {
		$totalVotes = $noVotes;
	}
	echo $before . $totalVotes . $after;
}

?>