Creating a Plugin to Add Votes to Your WordPress Comments Using AJAX

Creating a Plugin to Add Votes to Your WordPress Comments Using AJAX

Tutorial Details
  • Program: WordPress
  • Difficulty: Intermediate
  • Estimated Completion Time: 45 min

WordPress has a good posting system which is extendable so that WordPress can be used to build a lot of different sites rather than just a blog. WordPress also has a very extendable commenting system. The commenting system of WordPress can also be extended in different ways to be used in your WordPress sites. The commenting system can be used as a review forum if the WordPress site is to be made into a product catalog system. The commenting system can be used as answers to questions if the WordPress site is to be used for a Question and Answer site. So the commenting system in WordPress can be moulded or extended to provide functionality th at can enhance the complete site built on WordPress. In this article we are going to write a plugin to add a voting system on the comments which could be useful if the commenting system is used in a different way like in the examples stated above and many others that you can think up.


Step 1 Creating the Plugin

Let’s now start by creating the plugin. In our wp-content folder we will create a folder for our plugin called commentsvote. Inside the folder commentsvote create a file commentsvote.php which will be the main file of our plugin. Then we will add the plugin header as follows which will help WordPress to identify our plugin and show it in the plugin list in WordPress’ admin. The header is as follows.

<?php
/*
Plugin Name: Vote on Comments
Plugin URI: 
Description: Allows to add votes on comment
Author: Abbas Suterwala
Version: 
Author URI: 
*/
?>

Once we add the header we will be able to see our plugin in the plugin list as follows. We can now activate the plugin.

Now let’s setup some variables and scripts which we will use in our plugin. We create constants to define the plugin path and the plugin URL which can be used in different places in the plugin as follows.

<?php
define('VOTECOMMENTSURL', WP_PLUGIN_URL."/".dirname( plugin_basename( __FILE__ ) ) );
define('VOTECOMMENTPATH', WP_PLUGIN_DIR."/".dirname( plugin_basename( __FILE__ ) ) );
?>

Also as we are going to have the functionality to add votes via AJAX we will need a JavaScript file. To add the JavaScript file we create a js folder in our plugin folder and create a commentsvote.js file in it. Once we have created the necessary files our folder structure for the plugin will look as follows.

Then we enqueue the scripts so that the JS files are loaded by the WordPress engine as follows.

<?php
function voteme_enqueuescripts() {
	wp_enqueue_script('votecomment', VOTECOMMENTSURL.'/js/commentsvote.js', array('jquery'));
	wp_localize_script( 'votecomment', 'votecommentajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
}
add_action('wp_enqueue_scripts', voteme_enqueuescripts);
?>

Step 2 Understanding Some WordPress Function for Comments

WordPress provides support for comments meta in which we can store and retrieve some meta data related to the comment. We are going to store the votes on the comments as comment meta using these supporting functions. Hence here we are going to see what these functions are which WordPress provides.

The first function which we are going to see is get_comment_meta(). This function is similar to get_post_meta(). This function takes the first argument as the comment ID, the second argument as the name of the meta key, the third argument which if set to true returns the value as a string, if set to false or left blank will return an array of all the values for that key.

For more information you can visit the get_comment_meta() page in the WordPress Codex.

The other function which we are going to use is update_comment_meta. This function takes four arguments which are the comment ID, the meta key, the meta value and the previous value.

For more information you can visit the update_comment_meta() page in the WordPress Codex.


Step 3 Displaying the Current Votes Next to the Comment

Now let’s add the number of votes and a vote link next to each comment so that the users can vote on the comments. For this first we write a function which will create the link and return it as a string.

<?php
function commentsvote_showlink() {
	$link = "";
	$nonce = wp_create_nonce("commentsvote_nonce");
	$current_CommentID =  get_comment_ID();
	$votes = get_comment_meta($current_CommentID, '_commentsvote', true) != '' ? get_comment_meta($current_CommentID, '_commentsvote', true) : '0';
	$arguments = $current_CommentID.",'".$nonce."'";
	$link = $votes.' <a onclick="commentsvote_add('.$arguments.');">'.'Votes'.'</a>';
	$completelink = '<div id="commentsvote-'.$current_CommentID.'">';
	$completelink .= '<span>'.$link.'</span>';
	$completelink .= '</div>';
	return $completelink;
}
?>

In this function we first get the current comment ID using the WordPress function get_comment_ID(). Then we get the number of votes on comment the using the function get_comment_meta().

Then we create a link in which we call the JavaScript function commentsvote_add() which we will implement in the below steps.

Then let’s add this link to every comment using the filter comment_text. We hook into the filter comment_text and add the link as follows.

<?php
function commentsvote_comment_text($content) {
	return $content.commentsvote_showlink();
}
add_filter('comment_text', commentsvote_comment_text);
?>

Now if you visit the individual post page you will see the vote’s link as follows.


Step 4 Creating the AJAX Handler for Adding Votes on Comments

Now once we have created the code to show the link let’s create the AJAX handlers in WordPress to handle the request. The AJAX request handler is as follows.

<?php
function commentsvote_ajaxhandler() {
	if ( !wp_verify_nonce( $_POST['nonce'], "commentsvote_nonce")) {
		exit("Something Wrong");
	}

	$results = '';
	global $wpdb;

	$commentid = $_POST['commentid'];
	$votecount = get_comment_meta($commentid, '_commentsvote', true) != '' ? get_comment_meta($commentid, '_commentsvote', true) : '0';
	$votecountNew = $votecount + 1;
	update_comment_meta($commentid, '_commentsvote', $votecountNew);

	$results.='<div class="votescore" >'.$votecountNew.'</div>';

	//Return the String
	die($results);
}
// creating Ajax call for WordPress
add_action( 'wp_ajax_nopriv_commentsvote_ajaxhandler', 'commentsvote_ajaxhandler' );
add_action( 'wp_ajax_commentsvote_ajaxhandler', 'commentsvote_ajaxhandler' );
?>

In the AJAX handler we first verify the nonce. Then we get the comment ID and get the number of current votes on the comment using the function get_comment_meta(). Once that is done we increment the current count by one and then update the meta using the function update_comment_meta().

Then we return the updated value back from the AJAX handler.


Step 5 Voting on Comments via AJAX

Now once our link and the AJAX handlers are done we just need to write the JavaScript function to make the AJAX call. The function is as follows.

function commentsvote_add(comment_id,nonce) {

	jQuery.ajax({
		type: 'POST',
		url: votecommentajax.ajaxurl,
		data: {
			action: 'commentsvote_ajaxhandler',
			commentid: comment_id,
			nonce: nonce
		},
		success: function(data, textStatus, XMLHttpRequest) {
			var linkofcomment = '#commentsvote-' + comment_id;
			jQuery(linkofcomment).html('');
			jQuery(linkofcomment).append(data);
		},
		error: function(MLHttpRequest, textStatus, errorThrown) {
			alert(errorThrown);
		}
	});

}

The function basically gets the comment ID and the makes an AJAX call to the AJAX handler. Once the AJAX handler returns the value the JavaScript function retrieves the div of the comment and updates its content with the new number of votes. Now one can click on the vote to add one vote to the comment.


Step 6 Allowing Only Logged in Users to Vote

Now let’s enhance the plugin to give an option to the admin to allow only logged in users to vote on comments. To do this we first create a settings page for our plugin. Following is the code to create a settings page.

<?php
// Settings
add_action('admin_menu', 'commentvote_create_menu');
function commentvote_create_menu() {
	add_submenu_page('options-general.php','Comments Vote','Comments Vote','manage_options', __FILE__.'comments_settings_page','comments_settings_page');
}
function comments_settings_page() {
?>
	<div class="wrap">
	<?php
	if( isset( $_POST['commentvotesubmit'] ) ) {
		update_option( 'commentvotelogin' , $_POST[ 'commentvotelogin' ] );
	}
	?>
		<div id="commentvotesetting">
			<form id='commentvotesettingform' method="post" action="">
				<h1><?php echo 'Settings'; ?></h1>
				<input type = 'Radio' Name ='commentvotelogin' value= 'yes' <?php if( get_option('commentvotelogin') == 'yes' ) echo 'checked';?> >Voting allowed to only logged in users
				<br/>
				<input type = 'Radio' Name ='commentvotelogin' value= 'no' <?php if( get_option('commentvotelogin') != 'yes' ) echo 'checked';?> >Voting allowed to non logged in users
				<br/><br/>
				<p class="submit">
				<input type="submit" id="commentvotesubmit" name="commentvotesubmit" class="button-primary" value="<?php echo 'Save'; ?>" />
				</p>
			</form>
		</div>
	</div>
<?php }
?>

Now depending on the setting we will check whether the user is logged in or not before showing the vote link or make the link point to the login page. So the adapted functions commentsvote_showlink() and commentsvote_ajaxhandler() will look as follows.

<?php
function commentsvote_showlink() {
	$link = "";
	$nonce = wp_create_nonce("commentsvote_nonce");
	$current_CommentID =  get_comment_ID();
	$votes = get_comment_meta($current_CommentID, '_commentsvote', true) != '' ? get_comment_meta($current_CommentID, '_commentsvote', true) : '0';
	if( get_option('commentvotelogin') != 'yes' || is_user_logged_in() ) {

		$arguments = $current_CommentID.",'".$nonce."'";
		$link = $votes.' <a onclick="commentsvote_add('.$arguments.');">'.'Votes'.'</a>';
		$completelink = '<div id="commentsvote-'.$current_CommentID.'">';
		$completelink .= '<span>'.$link.'</span>';
		$completelink .= '</div>';
	}
	else {
		$register_link = site_url('wp-login.php', 'login') ;
		$completelink = '<div class="commentlink" >'." <a href=".$register_link.">".$votes." Votes"."</a>".'</div>';
	}
	return $completelink;
}
function commentsvote_ajaxhandler() {
	if ( !wp_verify_nonce( $_POST['nonce'], "commentsvote_nonce")) {
		exit("Something Wrong");
	}

	$results = '';
	global $wpdb;
	if( get_option('commentvotelogin') != 'yes' || is_user_logged_in() ) {

		$commentid = $_POST['commentid'];
		$votecount = get_comment_meta($commentid, '_commentsvote', true) != '' ? get_comment_meta($commentid, '_commentsvote', true) : '0';
		$votecountNew = $votecount + 1;
		update_comment_meta($commentid, '_commentsvote', $votecountNew);

		$results.='<div class="votescore" >'.$votecountNew.'</div>';
	}

	//Return the String
	die($results);
}
?>

So now in case if the admin makes it compulsory that logged in users can only vote and if the logged in user is not logged in he will be pointed to the login page as follows.


Step 7 Showing Most Vote Comments on the Post

Now let’s add the functionality to show below each post its top voted posts. To do this we will first have to fetch the comments for the post in descending order of its votes. There is no direct way to sort comments on the basis of their meta hence we will write a custom query for the same. We will write the following function to do it.

function commentsvote_get_top_voted_comments($post_id) {

	$commentids = array();
	global $wpdb;

	$request = "
		select * from $wpdb->comments , $wpdb->commentmeta where 
		$wpdb->comments.comment_post_ID = ".$post_id. 
		" AND $wpdb->comments.comment_ID = $wpdb->commentmeta.comment_ID 
		AND $wpdb->commentmeta.meta_key = '_commentsvote' 
		ORDER BY $wpdb->commentmeta.meta_value+0 DESC;
	";

	$comments = $wpdb->get_results($request);

	foreach ($comments as $comment) {
		array_push( $commentids , $comment->comment_ID );
	}

	return $commentids;
}

This function takes posts as input and then runs a custom query on the wp_comments and wp_commentmeta to fetch the list of top voted comments for the post.

Then we add a function to the filter the_content as follows to show the comment excerpt and the votes below the post.

function show_top_voted_comments($content) {

	$result = "";
	$post_ID = get_the_ID();

	$commentids = commentsvote_get_top_voted_comments($post_ID);

	if (count($commentids) > 0 )
		$result = "Top Comments for this post:<br/>";

	foreach ($commentids as $commentid) {
		$votecount = get_comment_meta($commentid, '_commentsvote', true) != '' ? get_comment_meta($commentid, '_commentsvote', true) : '0';
		$result .=get_comment_excerpt($commentid) .'('.$votecount.')'.'<br/>';
	}

	return $content.$result;

}
add_filter('the_content', show_top_voted_comments);

Now if we see the post it will look as follows.


Conclusion

In case WordPress is used for different kind of sites its basic system and functionalities might not be enough for the site. But as the WordPress system is very extendable we can write plugins like the above to provide extra functionality to suit our needs. So have fun while extending your WordPress site!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.derby-webdesign.co.uk Kevin

    Great tut, I’ve been wanting something similar for a while now. It’ll certainly come in handy :)

  • Pingback: Creating a Plugin to Add Votes to Your WordPress Comments Using AJAX | Qtiva

  • http://www.leachcreative.com Andrew

    This is a pretty interesting tut, thanks for sharing.

  • David

    Nice tutorial; is there an easy way to change it so a visitor can only vote on each comment once instead of as many times as they want?

  • http://www.boiteaweb.fr Julio Potier (BoiteAWeb.fr)

    Hello

    A nonce token is missing in commentvote_create_menu(), lines 11 12 13.

    See you

  • http://www.customicondesign.com Custom Icon Design

    introduce very clear. easy to follow. many thanks.

  • http://freakify.com/ Ahmad Awais

    Nice tips. easy to follow tutorial. But how about giving some nice look to the area where people will vote for the comments?

  • http://www.voxwebdesign.com Federico Schäfer

    Great Idea for a tutorial! Thanks!!

  • http://cloudofthemes.com Connor Crosby

    Nice tutorial – although I would have liked to know how to add thumbs up and down for voting.

  • http://www.cineindya.com kumar

    cool thanks guys

  • trkiwp

    Excelent post sir! Very clear for begginers thx!

    I have a question …at the start u get_commnet_meta

    “$votes = get_comment_meta($current_CommentID, ‘_commentsvote’, true)”

    if i am not wrong … it means… get_comment_meta(id of the comment, and the KEY )

    but there is nowhere in wordpress registered meta data follow this KEY … so … if i do request on noncreated meta key it will automaticly created one? Thx

    • http://find.brentshepherd.com Brent Shepherd

      Hi trkiwp, the meta entry won’t be created using get_comment_meta(), WordPress will return an empty string when the key doesn’t exist, as explained here: http://codex.wordpress.org/Function_Reference/get_comment_meta#Return_Value

      The meta entry will be created with the call to update_comment_meta( $commentid, '_commentsvote', $votecountNew ) in the commentsvote_ajaxhandler() function.

      That’s why Abbas uses the PHP ternary operation to set a default “0″ value if no value exists whenever he access the meta:

      $votecount = get_comment_meta($commentid, ‘_commentsvote’, true) != ” ? get_comment_meta($commentid, ‘_commentsvote’, true) : ’0′;

      Which can be rewritten in a much longer, but slightly easier to understand way:

      if ( get_comment_meta($commentid, ‘_commentsvote’, true) != ” )
      $votecount = get_comment_meta($commentid, ‘_commentsvote’, true)
      else
      $votecount = ’0′;

      Hope that helps!

  • http://www.sanjaykhemlani.com/ sanjay

    Thanks for the tutorial! the only missing part is the CSS of the thumbs up or down. We can figure that out :)

  • PIT

    Great tutorial!

    PS
    How protect yourself against adding multiple votes by one person? ;)

  • http://twitter.com/aguidis Adrien Guidis

    Hi,

    Thx for your tutorial.

    Actually a user who log off/ log in can vote again… how can we prevent this action ?

  • victor

    Nice tuto very useful, what about a tuto to add votes to wordpress post and query them by most voted, im sure this is more useful.

  • Pingback: 20 Useful WordPress Theme Tutorials and Resources - Streetsmash

  • avneeshchauhan86

    great article