I made a rating system for my wordpress articles. You can downvote or upvote and it updates a gauge. Here is what it looks like : http://bit.ly/1eXiAzt
I adapted a wptuts tutorial which just gave the possibility to uplike. As a result, I have a few difficulties to make my script fully functional. Here is my problem :
I would want to memorize if the user has liked or disliked the article and adapt the css. Currently, both buttons have the same style when the user has already voted.
Here are my files :
functions.php :
<?php
// RATING //
$timebeforerevote = 1;
add_action('wp_ajax_nopriv_post-like', 'post_like');
add_action('wp_ajax_post-like', 'post_like');
add_action('wp_ajax_nopriv_post-like', 'post_dislike');
add_action('wp_ajax_post-like', 'post_dislike');
wp_enqueue_script('like_post', get_template_directory_uri().'/post-like.js', array('jquery'), '1.0', true );
wp_localize_script('like_post', 'ajax_var', array(
'url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('ajax-nonce')
));
function post_like()
{
// Check for nonce security
$nonce = $_POST['nonce'];
if ( ! wp_verify_nonce( $nonce, 'ajax-nonce' ) )
die ( 'Busted!');
if(isset($_POST['post_like']))
{
// Retrieve user IP address
$ip = $_SERVER['REMOTE_ADDR'];
$post_id = $_POST['post_id'];
// Get voters'IPs for the current post
$meta_IP = get_post_meta($post_id, "voted_IP");
$voted_IP = $meta_IP[0];
if(!is_array($voted_IP))
$voted_IP = array();
// Get votes count for the current post
$meta_count = get_post_meta($post_id, "votes_count", true);
$meta_total = get_post_meta($post_id, "votes_total", true);
// Use has already voted ?
if(!hasAlreadyVoted($post_id))
{
$voted_IP[$ip] = time();
// Save IP and increase votes count
update_post_meta($post_id, "voted_IP", $voted_IP);
update_post_meta($post_id, "votes_count", ++$meta_count);
update_post_meta($post_id, "votes_total", ++$meta_total);
// Display count (ie jQuery return value)
echo $meta_count;
}
else
echo "already";
}
else if(isset($_POST['post_dislike']))
{
// Retrieve user IP address
$ip = $_SERVER['REMOTE_ADDR'];
$post_id = $_POST['post_id'];
// Get voters'IPs for the current post
$meta_IP = get_post_meta($post_id, "voted_IP");
$voted_IP = $meta_IP[0];
if(!is_array($voted_IP))
$voted_IP = array();
// Get votes count for the current post
$meta_count = get_post_meta($post_id, "votes_count", true);
$meta_total = get_post_meta($post_id, "votes_total", true);
// Use has already voted ?
if(!hasAlreadyVoted($post_id))
{
$voted_IP[$ip] = time();
// Save IP and increase votes count
update_post_meta($post_id, "voted_IP", $voted_IP);
update_post_meta($post_id, "votes_count", --$meta_count);
update_post_meta($post_id, "votes_total", ++$meta_total);
// Display count (ie jQuery return value)
echo $meta_count;
}
else
echo "already";
}
exit;
}
function hasAlreadyVoted($post_id)
{
global $timebeforerevote;
// Retrieve post votes IPs
$meta_IP = get_post_meta($post_id, "voted_IP");
$voted_IP = $meta_IP[0];
if(!is_array($voted_IP))
$voted_IP = array();
// Retrieve current user IP
$ip = $_SERVER['REMOTE_ADDR'];
// If user has already voted
if(in_array($ip, array_keys($voted_IP)))
{
$time = $voted_IP[$ip];
$now = time();
// Compare between current time and vote time
if(round(($now - $time) / 60) > $timebeforerevote)
return false;
return true;
}
return false;
}
function getPostDislikeLink($post_id)
{
$themename = "twentyeleven";
if(hasAlreadyVoted($post_id))
$output .=
'<span title="'.__('Too kind !', $themename).'" class="like dislike alreadyvoted"></span>';
else
$output .=
'<a href="#" data-post_id="'.$post_id.'" class="idislike">
<span title="'.__('Too kind !', $themename).'"class="qtip like dislike"></span></a>';
return $output;
}
function getPostLikeLink($post_id)
{
$themename = "twentyeleven";
if(hasAlreadyVoted($post_id))
$output .=
'<span title="'.__('Nasty !', $themename).'" class="like alreadyvoted"></span>';
else
$output .= '<a href="#" data-post_id="'.$post_id.'" class="ilike">
<span title="'.__('Nasty !', $themename).'"class="qtip like"></span></a>';
return $output;
}
function getPostTotalLike($post_id)
{
$vote_count = get_post_meta($post_id, "votes_count", true);
$vote_total = get_post_meta($post_id, "votes_total", true);
if(empty($vote_total)){
$pourcentage = 'novotes';
}
else if ($vote_count < 0){
$vote_count2 = abs($vote_count);
$votesPositifs = $vote_total - $vote_count2;
$pourcentage = ($votesPositifs * 100) / $vote_total;
}
else if($vote_count > 0){
$pourcentage = ($vote_count * 100) / $vote_total;
}
else{
$pourcentage = 50;
}
if($pourcentage == 'novotes'){
$barometre = '<li class="level0"></li><li class="level0"></li><li class="level0"></li><li class="level0"></li>';
}
else if($pourcentage < 30){
$barometre = '<li class="level1"></li><li class="level0"></li><li class="level0"></li><li class="level0"></li>';
}
else if($pourcentage < 60){
$barometre = '<li class="level1"></li><li class="level2"></li><li class="level0"></li><li class="level0"></li>';
}
else if($pourcentage < 85){
$barometre = '<li class="level1"></li><li class="level2"></li><li class="level3"></li><li class="level0"></li>';
}
else{
$barometre = '<li class="level1"></li><li class="level2"></li><li class="level3"></li><li class="level4"></li>';
}
$output2 .= '<ul>'.$barometre.'</ul>';
return $output2;
}
function getStats($post_id)
{
$vote_count = get_post_meta($post_id, "votes_count", true);
$vote_total = get_post_meta($post_id, "votes_total", true);
$output3 = '<span>Score : '.$vote_count.' / Total votes : '.$vote_total.'</span>';
return $output3;
}
?>
HTML :
<div class="mechancete post-like">
<?php echo getPostDislikeLink(get_the_ID());?>
<?php echo getPostTotalLike(get_the_ID());?>
<?php echo getPostLikeLink(get_the_ID());?>
<?php echo getStats(get_the_ID());?>
</div>
JS :
jQuery(document).ready(function() {
jQuery(".post-like a.ilike").click(function(){
heart = jQuery(this);
post_id = heart.data("post_id");
jQuery.ajax({
type: "post",
url: ajax_var.url,
data: "action=post-like&nonce="+ajax_var.nonce+"&post_like=&post_id="+post_id,
success: function(count){
if(count != "already")
{
heart.addClass("voted");
heart.siblings(".count").text(count);
}
}
});
return false;
})
jQuery(".post-like a.idislike").click(function(){
heart = jQuery(this);
post_id = heart.data("post_id");
jQuery.ajax({
type: "post",
url: ajax_var.url,
data: "action=post-like&nonce="+ajax_var.nonce+"&post_dislike=&post_id="+post_id,
success: function(count){
if(count != "already")
{
heart.addClass("voted");
heart.siblings(".count").text(count);
}
}
});
return false;
})
})
Thanks in advance for your help !
Two main issues:
the CSS classes don’t match, you have
ilike
,like
,idislike
anddislike
, make this consistent and meaningful to use with<a>
and<span>
.you should use
wp_send_json_success
, so you can pass$count
and$total
as array values to update the counter when processing the successful response. And you need to assign a class to the counter container, so as to update its value.As sidenote:
wrap all the enqueue into
wp_enqueue_scripts
the tutorial shows how to do this with
functions.php
, but that’s not correct, make your own plugin. What happens when you swap the theme?