I know it ain't perfect as it uses cookie (if you delete it, you just can vote or add hits again and again), but sounded to me the best way to go as I don't want to use IP blocking and user logging with password. I'm sure function can be improve, so just tell me what's wrong or what could be done better, or am I all wrong !! ;-)
I ain't expert in PHP but try to do my best.
This function will manage hit and vote count for sites in some kind of link directory.
Only 1 vote or hit is allowed by 24h for each user.
Cookie is used to hold a user id.
A mysql table called log with user_id as primary key will hold user records.
Records are arrays serialized in table log.
Vote and hit count will be apply to table called sites_list (table with all kind of information about sites with site_id being primary key).
Cron job will cleanup table log for outdated user row.
SQL :
CREATE TABLE log (
user_id varchar (32) NOT NULL,
user_vote_records text (1000),
user_hit_records text (1000),
user_id_timeout datetime NOT NULL,
PRIMARY KEY (user_cookie_id)
);
/
function hiVote return true if hit or vote has been count, false other way
@ $site_id (int) unique id of a site
@ $action (string) specified action : vote or hit
@ $vote_rating (int) optionnal (rating given for a site by user if action is vote)
/
function hitVote($site_id, $action, $vote_rating) {
if ($action == 'vote') $action_row = "user_vote_records";
if ($action == 'hit') $action_row = "user_hit_records";
$id_timeout = time()+(7*24*3600); // Set new timeout for user id (1 week)
$action_timeout = time()+(24*3600); // Set new timeout for site action (24h), when vote or hit is been count
$new_action[$site_id] = $action_timeout; // Add new timeout for this site action, when vote or hit is been count
$new_records = serialize($new_action);
$new_records = addslashes($new_records);
if (isset($_COOKIE['ID'])) {
$id = $_COOKIE['ID'];
$query = "SELECT user_id, $action_row FROM log WHERE user_id = '$id'";
$result = mysql_query($query);
$log_row = mysql_fetch_array($result);
if (isset($log_row['user_id'])) { // User already has some records in DB
if(isset($log_row[$action_row])) { // If records specified by action (vote or hit) exist
$records = unserialize($log_row[$action_row]);
stripslashes($records);
reset($records);
if (array_key_exists($site_id, $records) && ($records[$site_id] > time())) { // If timeout hasn't ended for this site action, return false
return false;
} else { // If timeout has ended, count new vote or new hit ($query_site_upd) and set new timeout for this site action
$records[$site_id] = $action_timeout;
$upd_records = serialize($records);
$upd_records = addslashes($upd_records);
$query_log_upd = "UPDATE log SET $action_row = '$upd_records', user_id_timeout = '".date("Y-m-d H:i:s", $id_timeout)."' WHERE user_id
= '$id'";
}
} else { // If records specified by action (vote or hit) don't exist
$query_log_upd = "INSERT INTO log SET ";
$query_log_upd.= "$action_row = '$new_records', ";
$query_log_upd.= "user_id_timeout = '".date("Y-m-d H:i:s",$id_timeout)."' WHERE user_id = '$id'";
}
}
}
if (!isset($_COOKIE['ID']) || !isset($log_row['id'])) { // If cookie don't exist or user id isn't in DB ( user row are erazed by cron job when outdated)
$id = md5(uniqid(time()));
$query_log_upd = "INSERT INTO log SET ";
$query_log_upd.= "user_id = '$id', ";
$query_log_upd.= "$action_row = ";
$query_log_upd.= "'$new_records', ";
$query_log_upd.= "user_id_timeout = '".date("Y-m-d H:i:s",$id_timeout)."'";
}
if ($action == 'vote') {
$query = "SELECT site_votes, site_votes_rating FROM sites_list WHERE site_id = '$site_id'";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
$new_rating = (($row['site_votes'] * $row['site_votes_rating']) + $vote_rating) / ($row['site_votes'] +1);
$query_site_upd = "UPDATE sites_list SET site_votes = site_votes+1, site_votes_rating = $new_rating WHERE site_id = '$site_id'";
} elseif ($action == 'hit') {
$query_site_upd = "UPDATE sites_list SET site_hits = site_hits+1 WHERE site_id = '$site_id'";
}
// cookie UPDATE
setcookie("ID", $id, $id_timeout, "/");
mysql_query($query_site_upd);
mysql_query($query_log_upd);
return true;
}