PageID = $pageID; $this->Username = $wgUser->getName(); $this->Userid = $wgUser->getID(); } /** * Counts all votes, fetching the data from memcached if available * or from the database if memcached isn't available * * @return int Amount of votes */ function count() { $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); $logger = LoggerFactory::getInstance( 'VoteNY' ); $key = 'vote_count_'.$this->PageID; $data = $cache->get( $key ); // Try cache if ( $data ) { $logger->debug( "Loading vote count for page {$this->PageID} from cache\n" ); $vote_count = $data; } else { $lb = MediaWikiServices::getInstance()->getDBLoadBalancer(); $dbr = $lb->getConnection( DB_PRIMARY ); $vote_count = 0; $res = $dbr->select( 'Vote', 'COUNT(*) AS votecount', array( 'vote_page_id' => $this->PageID ), __METHOD__ ); $row = $res->fetchRow(); if ( $row ) { $vote_count = $row->votecount; } $cache->set( $key, $vote_count ); } return $vote_count; } /** * Gets the average score of all votes * * @return int Formatted average number of votes (something like 3.50) */ function getAverageVote() { $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); $logger = LoggerFactory::getInstance( 'VoteNY' ); $key = 'vote_avg_'.$this->PageID; $data = $cache->get( $key ); $voteAvg = 0; if ( $data ) { $logger->debug( "Loading vote avg for page {$this->PageID} from cache\n" ); $voteAvg = $data; } else { $lb = MediaWikiServices::getInstance()->getDBLoadBalancer(); $dbr = $lb->getConnection( DB_PRIMARY ); $res = $dbr->select( 'Vote', 'AVG(vote_value) AS voteavg', array( 'vote_page_id' => $this->PageID ), __METHOD__ ); $row = $res->fetchRow(); if ( $row ) { $voteAvg = $row->voteavg; } $cache->set( $key, $voteAvg ); } return number_format( $voteAvg, 2 ); } /** * Clear caches - memcached, parser cache and Squid cache */ function clearCache() { global $wgUser; // Kill internal cache $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); $cache->delete( 'vote_count_'.$this->PageID ); $cache->delete( 'vote_avg_'.$this->PageID ); // Purge squid $pageTitle = Title::newFromID( $this->PageID ); if ( is_object( $pageTitle ) ) { $pageTitle->invalidateCache(); $pageTitle->purgeSquid(); // Kill parser cache $article = new Article( $pageTitle, /* oldid */0 ); $parserCache = ParserCache::singleton(); $parserKey = $parserCache->getKey( $article, $wgUser ); $cache->delete( $parserKey ); } } /** * Delete the user's vote from the database, purges normal caches and * updates SocialProfile's statistics, if SocialProfile is active. */ function delete() { $dbw = wfGetDB( DB_MASTER ); $dbw->delete( 'Vote', array( 'vote_page_id' => $this->PageID, 'username' => $this->Username ), __METHOD__ ); $this->clearCache(); // Update social statistics if SocialProfile extension is enabled if ( class_exists( 'UserStatsTrack' ) ) { $stats = new UserStatsTrack( $this->Userid, $this->Username ); $stats->decStatField( 'vote' ); } } /** * Inserts a new vote into the Vote database table * * @param int $voteValue */ function insert( $voteValue ) { global $wgRequest; $dbw = wfGetDB( DB_MASTER ); wfSuppressWarnings(); // E_STRICT whining $voteDate = date( 'Y-m-d H:i:s' ); wfRestoreWarnings(); if ( $this->UserAlreadyVoted() == false ) { $dbw->insert( 'Vote', array( 'username' => $this->Username, 'vote_user_id' => $this->Userid, 'vote_page_id' => $this->PageID, 'vote_value' => $voteValue, 'vote_date' => $voteDate, 'vote_ip' => $wgRequest->getIP(), ), __METHOD__ ); $this->clearCache(); // Update social statistics if SocialProfile extension is enabled if ( class_exists( 'UserStatsTrack' ) ) { $stats = new UserStatsTrack( $this->Userid, $this->Username ); $stats->incStatField( 'vote' ); } } } /** * Checks if a user has already voted * * @return bool|int False if s/he hasn't, otherwise returns the * value of 'vote_value' column from Vote DB table */ function UserAlreadyVoted() { $lb = MediaWikiServices::getInstance()->getDBLoadBalancer(); $dbr = $lb->getConnection( DB_PRIMARY ); $s = $dbr->selectRow( 'Vote', array( 'vote_value' ), array( 'vote_page_id' => $this->PageID, 'username' => $this->Username ), __METHOD__ ); if ( $s === false ) { return false; } else { return $s->vote_value; } } /** * Displays the green voting box * * @return string HTML output */ function display() { global $wgUser; $voted = $this->UserAlreadyVoted(); $make_vote_box_clickable = ''; if ( $voted == false ) { $make_vote_box_clickable = ' vote-clickable'; } $output = "
"; $output .= '' . $this->count() . ''; $output .= '
'; $output .= '
'; if ( !$wgUser->isAllowed( 'voteny' ) ) { // @todo FIXME: this is horrible. If we don't have enough // permissions to vote, we should tell the end-user /that/, // not require them to log in! $login = SpecialPage::getTitleFor( 'Userlogin' ); $output .= '' . wfMessage( 'voteny-link' )->plain() . ''; } else { if ( !wfReadOnly() ) { if ( $voted == false ) { $output .= '' . wfMessage( 'voteny-link' )->plain() . ''; } else { $output .= '' . wfMessage( 'voteny-unvote-link' )->plain() . ''; } } } $output .= '
'; return $output; } } /** * Class for generating star rating stars. */ class VoteStars extends Vote { public $maxRating = 5; /** * Displays voting stars * * @param bool $voted Has the user already voted? False by default * @return string HTML output */ function display( $voted = false ) { global $wgUser; $overall_rating = $this->getAverageVote(); if ( $voted ) { $display_stars_rating = $voted; } else { $display_stars_rating = $this->getAverageVote(); } $id = ''; // Should probably be $this->PageID or something? // 'cause we define $id just above as an empty string...duh $output = '
'; $output .= '
'; $output .= '
' . $overall_rating . '
'; $output .= '
'; $output .= '
'; $output .= $this->displayStars( $id, $display_stars_rating, $voted ); $count = $this->count(); if ( isset( $count ) ) { $output .= ' (' . wfMessage( 'voteny-votes', $count )->parse() . ')'; } $already_voted = $this->UserAlreadyVoted(); if ( $already_voted && $wgUser->isLoggedIn() ) { $output .= '
' . wfMessage( 'voteny-gave-this', $already_voted )->parse() . "
PageID}\" data-vote-id=\"{$id}\">(" . wfMessage( 'voteny-remove' )->plain() . ')'; } $output .= '
'; $output .= '
'; return $output; } /** * Displays the actual star images, depending on the state of the user's mouse * * @param int $id ID of the rating (div) element * @param int $rating Average rating * @param int $voted * @return string Generated tag */ function displayStars( $id, $rating, $voted ) { global $wgExtensionAssetsPath; if ( !$rating ) { $rating = 0; } if ( !$voted ) { $voted = 0; } $output = ''; for ( $x = 1; $x <= $this->maxRating; $x++ ) { if ( !$id ) { $action = 3; } else { $action = 5; } $output .= "PageID}\"" . " data-vote-id=\"{$id}\" data-vote-action=\"{$action}\" data-vote-rating=\"{$rating}\"" . " data-vote-voted=\"{$voted}\" id=\"rating_{$id}_{$x}\"" . " src=\"{$wgExtensionAssetsPath}/VoteNY/images/star_"; switch ( true ) { case $rating >= $x: if ( $voted ) { $output .= 'voted'; } else { $output .= 'on'; } break; case ( $rating > 0 && $rating < $x && $rating > ( $x - 1 ) ): $output .= 'half'; break; case ( $rating < $x ): $output .= 'off'; break; } $output .= '.gif" alt="" />'; } return $output; } /** * Displays the average score for the current page * and the total amount of votes. * * @return string */ function displayScore() { $count = $this->count(); return wfMessage( 'voteny-community-score', '' . $this->getAverageVote() . '' ) ->numParams( $count )->text() . ' (' . wfMessage( 'voteny-ratings' )->numParams( $count )->parse() . ')'; } }