* * See CONFIGURATION below. * * @author Michelle Steigerwalt * @copyright 2007 Michelle Steigerwalt * @license LGPL 2.1 . */ class RabidRatings { /* Edit the lines below to configure this widget. */ function configuration() { /////////////////////////////////////////////////////////////////////////////// ////////// CONFIGURATION ////////// /////////////////////////////////////////////////////////////////////////////// /* Database Connection Options */ $this->dbHost = "localhost"; //The host to connect to. $this->dbUser = "username"; //The username to login as. $this->dbPassword = "secret"; //The database password. $this->dbDatabase = "myDatabase"; //The database to utilize. $prefix = "rabid_"; //The prefix to the db table. $this->ratables = $prefix."ratables"; //The name of the ratables table. $this->ratings = $prefix."ratings"; //The name of the ratings table. //The position of the vote stat text. Can be "before", "after", or //false. $this->textPosition = "before"; //If allowDuplicates is set to true, people can vote multiple times //for the same item. NOTE: This has to be set before the table is //created. To change the value, you must first DROP all related //tables so they can be recreated. (Or you can be a dirty hack and //change $ip in doVote to rand(1,1000) or something.) $this->allowDuplicates = false; //The total number of stars in the scale (ie, 5). $this->stars = 5; /////////////////////////////////////////////////////////////////////////////// ////////// END OF CONFIGURATION: Do Not Modify Below Lines ////////// /////////////////////////////////////////////////////////////////////////////// } function RabidRatings() { $this->configuration(); $this->initializeDatabase(); } /** * RabidRatings::showStars * Outputs the HTML code for a ratings box, including the current score (if * any) of the item being rated. * * @param string ratableKey - The unique idenifier for your rateable item. * ratableKey should be made up in whatever manner works best for the * site using it. */ function showStars($ratableKey) { $rating = $this->loadRating($ratableKey); $ratingId = $rating['keyID']; $stars = $this->percentToStars($rating['rating']); $percent = round($rating['rating'], 0)."%"; if ($rating['totalRatings'] == 0) { $unratedClass = " ratingUnrated"; } $textDesc = "
" .$this->getStarMessage($rating)."
"; if ($this->textPosition == "before") { $beforeText = $textDesc; } else if ($this->textPosition == "after") { $afterText = $textDesc; } /* Here's where you would mess with the code to modify the template. */ echo "
stars\" " ."class=\"rabidRating$unratedClass\">" .$beforeText ."
" ."" ."" ."
".$afterText."
"; } function getStarMessage($rating) { $stars = $this->percentToStars($rating['rating']); if ($rating[totalRatings] > 1) $s = "s"; return "$stars/$this->stars stars ($rating[totalRatings] vote$s)"; } /** * RabidRatings::doVote * * This is the function in charge of handling a vote and saving it to the * database. * * NOTE: This method is meant to be called as part of an AJAX request. As * such, it unitlizes the die() function to display its errors. THIS * WOULD BE A VERY BAD FUNCTION TO CALL FROM WITHIN ANOTHER PAGE. * * @param integer id - The id of key to register a rating for. * @param integer percent - The rating in percentages. */ function doVote($ratableId, $percent) { $ip = $_SERVER['REMOTE_ADDR']; //Make sure that the ratable ID is a number and not something crazy. if (is_numeric($ratableId)) { $id = $ratableId; } else { die("ERROR: Id invalid."); } //Make sure the percent is a number and under 100. if (is_numeric($percent) && $percent < 101) { $rating = $percent; } else { die("ERROR: Rating percent invalid."); } //Insert the data. $SQL_INSERT_VOTE = "INSERT INTO $this->ratings(ratable_id, ip_address, ". "rating) VALUES ('$id', '$ip', '$rating');"; //Die with an error if the insert fails (duplicate IP for a vote). if (!mysql_query($SQL_INSERT_VOTE)) { die("ERROR: Duplicate votes not allowed."); } $rating = $this->loadRating($id); echo $this->getStarMessage($rating); } /** * RabidRatings::initializeDatabase * * Connects to the database, returning false on failure. * NOTE: It's my intention here to be as unobtrusive as possible upon a * failure, since nobody likes their entire page dying and throwing ugly * errors just because a minor widget fails. */ function initializeDatabase() { error_reporting(1); $this->dbConnection = mysql_connect($this->dbHost, $this->dbUser, $this->dbPassword); if (!mysql_select_db($this->dbDatabase)) { echo("RabidRatings couldn't connect to the database. Please make " ."sure your configuration is correct."); } else { $this->ensureTables(); } } /** * RabidRatings::ensureTables * Creates the necessary database tables, should they not exist. */ function ensureTables() { if (!$this->allowDuplicates) { $unique = ", UNIQUE KEY `ratableKey` (`ratableKey`)"; } $SQL_CREATE_RATABLES = "CREATE TABLE $this->ratables ( `id` int(11) NOT NULL auto_increment, `ratableKey` varchar(50) NOT NULL, `created_at` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`id`) $unique ) AUTO_INCREMENT=1 ; "; $SQL_CREATE_RATINGS = "CREATE TABLE $this->ratings ( `id` int(11) NOT NULL auto_increment, `ratable_id` int(11) NOT NULL, `ip_address` varchar(50) NOT NULL, `rating` int(11) NOT NULL, `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE ( `ratable_id` , `ip_address`), CONSTRAINT rabid_ratings_fk FOREIGN KEY (`ratable_id`) REFERENCES $this->ratables(id) ) AUTO_INCREMENT=1 ;"; $result = mysql_query("SHOW TABLES;"); while ($table = mysql_fetch_array($result)) { if ($table[0] == $this->ratables) { $ratablesFound = true; } if ($table[0] == $this->ratings) { $ratingsFound = true; } } if ($ratablesFound != true) { mysql_query($SQL_CREATE_RATABLES); } if ($ratingsFound != true) { mysql_query($SQL_CREATE_RATINGS); } } function loadRating($ratableKey) { if (is_numeric($ratableKey)) $crit = "$this->ratables.id"; else $crit = 'ratableKey'; $WHERE = "WHERE $crit = '$ratableKey'"; $SQL_GET_RATINGS = "SELECT $this->ratables.id AS keyID, AVG( $this->ratings.rating ) AS rating, COUNT( $this->ratings.rating ) AS totalRatings FROM $this->ratables JOIN $this->ratings ON ( $this->ratables.id = $this->ratings.ratable_id ) $WHERE GROUP BY $this->ratables.id;"; $result = mysql_fetch_array(mysql_query($SQL_GET_RATINGS), MYSQL_ASSOC); if ($result == null) { $result = $this->createNewKey($ratableKey); } return $result; } function createNewKey($key) { if (is_numeric($key)) { return false; } $SQL_INSERT_KEY = "INSERT INTO $this->ratables(ratableKey) " ."VALUES ('$key');"; $SQL_GET_NEW_KEY = "SELECT id AS keyID FROM $this->ratables WHERE " ."ratableKey = '$key';"; mysql_query($SQL_INSERT_KEY); $newKey = mysql_fetch_array(mysql_query($SQL_GET_NEW_KEY), MYSQL_ASSOC); $newKey['rating'] = 0; $newKey['totalRatings'] = 0; return $newKey; } function percentToStars($percent) { $modifier = 100 / $this->stars; return round($percent / $modifier, 1); } } /* The code below handles ratings sent if the $_POST variables are set. */ if ($_POST['vote'] && $_POST['id']) { $r = new RabidRatings(); $r->doVote($_POST['id'], $_POST['vote']); }; ?>