Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

There's code below for simple post rating system (tutorial from this site TUTORIAL ) - it works fine but i need to change it a bit. Now where user votes, he is not able to vote again for same post for $timebeforevote (1440 minutes). I want to block user voting for all post not just for this one.

I think the problem is function is looking for user ip in current post meta field with this code:

$meta_IP = get_post_meta($post_id, "voted_IP");
$voted_IP = $meta_IP[0];

Returns $voted_IP and compares it with $ip = $_SERVER['REMOTE_ADDR']; I tried to modify it with query (where query looks for ip in meta field for all posts) so it would search for ip in all posts but it didn't work. I am trying to make it work for 2 days and nothing works.

POST RATING SYSTEM CODE:

$timebeforerevote = 1440;

add_action('wp_ajax_nopriv_post-like', 'post_like');
add_action('wp_ajax_post-like', 'post_like');

wp_enqueue_script('like_post', get_template_directory_uri().'/js/post-like.js', array('jquery'), '1.0', 1 );
wp_localize_script('like_post', 'ajax_var', array(
    'url' => admin_url('admin-ajax.php'),
    'nonce' => wp_create_nonce('ajax-nonce')
));

function post_like()
{
    $nonce = $_POST['nonce'];

    if ( ! wp_verify_nonce( $nonce, 'ajax-nonce' ) )
        die ( 'Busted!');

    if(isset($_POST['post_like']))
    {
        $ip = $_SERVER['REMOTE_ADDR'];
        $post_id = $_POST['post_id'];

        $meta_IP = get_post_meta($post_id, "voted_IP");

        $voted_IP = $meta_IP[0];
        if(!is_array($voted_IP))
            $voted_IP = array();

        $meta_count = get_post_meta($post_id, "votes_count", true);

        if(!hasAlreadyVoted($post_id))
        {
            $voted_IP[$ip] = time();

            update_post_meta($post_id, "voted_IP", $voted_IP);
            update_post_meta($post_id, "votes_count", ++$meta_count);

            echo $meta_count;
        }
        else
            echo "already";
    }
    exit;
}

function hasAlreadyVoted($post_id)
{
    global $timebeforerevote;

    $meta_IP = get_post_meta($post_id, "voted_IP");
    $voted_IP = $meta_IP[0];
    if(!is_array($voted_IP))
        $voted_IP = array();
    $ip = $_SERVER['REMOTE_ADDR'];

    if(in_array($ip, array_keys($voted_IP)))
    {
        $time = $voted_IP[$ip];
        $now = time();

        if(round(($now - $time) / 60) > $timebeforerevote)
            return false;

        return true;
    }

    return false;
}

function getPostLikeLink($post_id)
{
    $themename = "twentyeleven";

    $vote_count = get_post_meta($post_id, "votes_count", true);

    $output = '<p class="post-like">';

    if ($vote_count == 0)
        $output .= '<span class="count">0<span class="glosow"><br>głosów w rankingu</span></span>';
    else
        $output .= '<span class="count">'.$vote_count.'<span class="glosow"><br>głosów w rankingu</span></span>';

    if(hasAlreadyVoted($post_id))
        $output .= '<span title="Już głosowałeś" class="qtip alreadyvoted"></span>';
    else
        $output .= '<a href="#" data-post_id="'.$post_id.'">
                    <span  title="'.__('Głosuj', $themename).'"class="qtip like"></span></a>';
    $output .= '</p>';

    return $output;
}
share|improve this question
add comment

1 Answer

up vote 0 down vote accepted

What you want is actually pretty easy to achieve. The code from the tutorial you used saves and gets the data post dependent via update_post_meta() and get_post_meta(), which doesn't suit your use case.

You just have to store your data post independent. This thought relates to the array of IP keys and time values you need for the timed restriction of the voting system you implemented. You can and probably should leave the way the vote count is saved untouched, because it's logical to save this information post dependent.

Probably the easiest way to achieve saving the »[IP] => [time]« array post independent is by making use of the Options API. Thereby using the functions offered by the API as replacement for the post meta functions that are now used by your code. The functions you are going to need are: update_option() and get_option().

Below I'm outlining how to use them:

//option name
$opt_nam = 'def_opt_nam';

//get IP and TIME
$ip = $_SERVER['REMOTE_ADDR'];
$time = time();
//current visitor key:IP => value:TIME pair
$cvi_ipt = array (
    $ip => $time
);

//get the data array
$opt_arr = get_option( $opt_nam );

//update data array
//merge current visitor array with the data array from the options table
//if the key doesn't exist the a new pair is created, if a key exists the value gets updated
$upd_opt = array_merge( $opt_arr, $cvi_ipt );
//actually do the update
update_option( $opt_nam, $upd_opt );

Of course the code above is exemplary. You have to replace the post dependent approach, using post meta, with the suggested and outlined post independent one working with the Options API yourself. But this shouldn't be all that hard to do now.


Update:

function post_like()
{
    $nonce = $_POST['nonce'];

    if ( ! wp_verify_nonce( $nonce, 'ajax-nonce' ) )
        die ( 'Busted!');

    if(isset($_POST['post_like']))
    {
        $ip = $_SERVER['REMOTE_ADDR'];
        $post_id = $_POST['post_id'];

        $voted_IP = get_option( "voted_IP" );

        if(!is_array($voted_IP))
            $voted_IP = array();

        $meta_count = get_post_meta($post_id, "votes_count", true);

        if(!hasAlreadyVoted())
        {

            $ip = $_SERVER['REMOTE_ADDR'];
            $time = time();
            $cvi_ipt = array (
                $ip => $time
            );
            $upd_opt = array_merge( $voted_IP, $cvi_ipt );

            update_option( "voted_IP", $upd_opt );
            update_post_meta($post_id, "votes_count", ++$meta_count);

            echo $meta_count;
        }
        else
            echo "already";
    }
    exit;
}

function hasAlreadyVoted()
{
    global $timebeforerevote;

    $voted_IP = get_option( "voted_IP" );

    if(!is_array($voted_IP))
        $voted_IP = array();

    $ip = $_SERVER['REMOTE_ADDR'];

    if(in_array($ip, array_keys($voted_IP)))
    {
        $time = $voted_IP[$ip];
        $now = time();

        if(round(($now - $time) / 60) > $timebeforerevote)
            return false;

        return true;
    }

    return false;
}

I implemented my suggestion into the code you posted in your question, but it's untested.


Edit:
In response to the comment. Like I said before, the only thing to do was changing the place where the data is stored. To elaborate a little bit on that: Post meta is post depending - you can recognize that by the fact that you are using the post id to save and get the meta data from the wp_postmeta table. In contrast the options api stores data inside the wp_options table. The way I suggested the code this is post independent, because one option is used to store all the data - key:ip => value:time pairs - from all posts. That's in (very) few words about it.

share|improve this answer
    
OK I'll try to do it myself but for php beginner its quite hard (I dealed with simpier wordpress problems for now) . –  th3rion Nov 1 '13 at 16:53
    
Give it a try, you really just have to replace the parts accordingly. @ŁukaszSzerejko –  ialocin Nov 1 '13 at 16:57
    
Hmm can't make it work. Too soon - code is too complicated for me. I'll try to go through it later and learn how to do it myself but for now I think I will have to pay someone to do it for me. Thank you for your time. –  th3rion Nov 1 '13 at 17:42
    
Hmmm too bad, give me some minutes to go over the code. Maybe I can make it simpler for you. @ŁukaszSzerejko –  ialocin Nov 1 '13 at 17:47
    
OMG love you man it works - you literally saved my live. I'll go through your code and try to see what was wrong. –  th3rion Nov 1 '13 at 18:12
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.