RatingExtension/Source Code
From PeacockWiki
(Difference between revisions)
Revision as of 02:11, 30 July 2006 (edit) Trevorp (Talk | contribs) ← Previous diff |
Revision as of 04:34, 30 July 2006 (edit) Trevorp (Talk | contribs) Next diff → |
||
Line 1: | Line 1: | ||
<pre><?php | <pre><?php | ||
- | #If html request requests file, serve file | + | ################################################################################ |
+ | # Core Code # | ||
+ | ################################################################################ | ||
+ | # This section handles the core functions of this extension # | ||
+ | # * Serving Files # | ||
+ | # * Recording Ratings # | ||
+ | # * Displaying Ratings # | ||
+ | ################################################################################ | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # If html request requests file, serve file # | ||
+ | # Files are requested by adding the ?file= GET parameter # | ||
+ | #------------------------------------------------------------------------------- | ||
if(isset($_GET['file'])) | if(isset($_GET['file'])) | ||
doFile(); | doFile(); | ||
- | #If html request contains rate information, process it | + | #------------------------------------------------------------------------------- |
+ | # If html request contains rate information, process it # | ||
+ | # Rating information indicated by ?rate= GET parameter # | ||
+ | # # | ||
+ | # MediaWiki engine is started by imitating the code in index.php # | ||
+ | # This ensures database functions are working # | ||
+ | #------------------------------------------------------------------------------- | ||
if(isset($_GET['rate'])) | if(isset($_GET['rate'])) | ||
{ | { | ||
Line 15: | Line 33: | ||
$action = $wgRequest->getVal( 'action', 'view' ); | $action = $wgRequest->getVal( 'action', 'view' ); | ||
$title = $wgRequest->getVal( 'title' ); | $title = $wgRequest->getVal( 'title' ); | ||
- | $wgTitle = $mediaWiki->checkInitialQueries( $title,$action,$wgOut, $wgRequest, $wgContLang ); | + | $wgTitle = $mediaWiki->checkInitialQueries($title, $action, $wgOut, |
+ | $wgRequest, $wgContLang); | ||
#Record Rating | #Record Rating | ||
#---------------- | #---------------- | ||
- | $sql = "REPLACE INTO `ratings` (`page_oldid`, `user_id`, `page_rating`) VALUES (".$_GET['oldid'].", '".($wgUser->getID()?$wgUser->getID():$wgUser->getName())."', ".$_GET['rate'].")"; | + | $sql = "REPLACE INTO `ratings` (`page_oldid`, `user_id`, `page_rating`) '. |
+ | 'VALUES (".$_GET['oldid'].", '". | ||
+ | ($wgUser->getID()?$wgUser->getID():$wgUser->getName()). | ||
+ | "', ".$_GET['rate'].")"; | ||
$dbr =& wfGetDB( DB_WRITE ); | $dbr =& wfGetDB( DB_WRITE ); | ||
$res=wfQuery($sql, DB_WRITE, ""); | $res=wfQuery($sql, DB_WRITE, ""); | ||
Line 31: | Line 53: | ||
} | } | ||
- | #get oldid of current page | + | #------------------------------------------------------------------------------- |
+ | # Initialize extension # | ||
+ | # Sets up credit information, and hooks # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | if(isset($wgScriptPath)) | ||
+ | { | ||
+ | $wgExtensionCredits["parserhook"][]=array( | ||
+ | 'name' => 'Rating Extension', | ||
+ | 'version' => '0.1', | ||
+ | 'url' => 'http://wiki.peacocktech.com/wiki/RatingExtension', | ||
+ | 'author' => '[http://about.peacocktech.com/trevorp/ Trevor Peacock]', | ||
+ | 'description' => 'Adds rating mechanism' ); | ||
+ | $wgHooks['OutputPageBeforeHTML'][] = 'InsertRating'; | ||
+ | $wgHooks['SkinTemplateSetupPageCss'][] = 'RatingCss'; | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Insert rating to top of page # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function InsertRating($parserOutput, $text) { | ||
+ | global $wgArticle; | ||
+ | $oldid=getOldID($wgArticle); | ||
+ | if($oldid) | ||
+ | $text='<div id="ratingsection">'. | ||
+ | getRatingHTML(getRating($oldid), $oldid).'</div>'.$text; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Add CSS into skin for rating # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function RatingCss(&$css) { | ||
+ | global $wgScriptPath; | ||
+ | $css = "/*<![CDATA[*/". | ||
+ | " @import \"$wgScriptPath/?file=rating.css\"; ". | ||
+ | "/*]]>*/"; | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | ################################################################################ | ||
+ | # Supporting Functions # | ||
+ | ################################################################################ | ||
+ | # These functions support the core functions of the extension # | ||
+ | ################################################################################ | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Use the mediawiki engine to run the given sql code and return an object # | ||
+ | # containing the first result of the query # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | #run sql code | ||
+ | function runQuery($sql) | ||
+ | { | ||
+ | $dbr =& wfGetDB( DB_SLAVE ); | ||
+ | $res=wfQuery($sql, DB_SLAVE, ""); | ||
+ | return $dbr->fetchObject( $res ); | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Return the oldid of the current page # | ||
+ | # If oldid=0 (most current revision) take the latest oldid from the database # | ||
+ | # for the current article # | ||
+ | #------------------------------------------------------------------------------- | ||
function getOldID($article) | function getOldID($article) | ||
{ | { | ||
Line 38: | Line 122: | ||
return $oldid; | return $oldid; | ||
$dbr =& wfGetDB( DB_SLAVE ); | $dbr =& wfGetDB( DB_SLAVE ); | ||
- | $sql = "SELECT MAX(`rc_this_oldid`) AS `rc_this_oldid` FROM recentchanges WHERE rc_cur_id=".$article->getID().";"; | + | $sql = "SELECT MAX(`rc_this_oldid`) AS `rc_this_oldid` FROM recentchanges '. |
- | $res=wfQuery($sql, DB_WRITE, ""); | + | 'WHERE rc_cur_id=".$article->getID().";"; |
+ | $res=wfQuery($sql, DB_SLAVE, ""); | ||
$row=$dbr->fetchObject( $res ); | $row=$dbr->fetchObject( $res ); | ||
if($row->rc_this_oldid) | if($row->rc_this_oldid) | ||
Line 46: | Line 131: | ||
} | } | ||
- | #run sql code | + | #------------------------------------------------------------------------------- |
- | function runQuery($sql) | + | # Performs a SQL query to fetch a rating for page oldid # |
- | { | + | #------------------------------------------------------------------------------- |
- | $dbr =& wfGetDB( DB_SLAVE ); | + | |
- | $res=wfQuery($sql, DB_SLAVE, ""); | + | |
- | return $dbr->fetchObject( $res ); | + | |
- | } | + | |
- | + | ||
- | #perform sql query to fetch rating for a given oldid | + | |
function getRatingData($oldid) | function getRatingData($oldid) | ||
{ | { | ||
- | $sql="SELECT COUNT(*) AS `count`, AVG(`page_rating`) AS `rating` FROM ratings WHERE `page_oldid`=".$oldid." GROUP BY `page_oldid`;"; | + | $sql="SELECT COUNT(*) AS `count`, AVG(`page_rating`) AS `rating` '. |
+ | 'FROM ratings WHERE `page_oldid`=".$oldid." GROUP BY `page_oldid`;"; | ||
return runQuery($sql); | return runQuery($sql); | ||
} | } | ||
- | #fetch/calculate rating from database | + | #------------------------------------------------------------------------------- |
+ | # Fetch and calculate a rating for page oldid # | ||
+ | # If there are not enough ratings for the current revivion, cycle # | ||
+ | # older revisions to gather a minimum number of ratings # | ||
+ | #------------------------------------------------------------------------------- | ||
function getRating($oldid) | function getRating($oldid) | ||
{ | { | ||
Line 71: | Line 155: | ||
$finalrating='?'; | $finalrating='?'; | ||
$currentcount=number_format($ratingdata->count, 0); | $currentcount=number_format($ratingdata->count, 0); | ||
+ | #If there are not enough ratings for the current revision | ||
if($rating->count<$countlimit) | if($rating->count<$countlimit) | ||
{ | { | ||
$count=$ratingdata->count; | $count=$ratingdata->count; | ||
$rating=$count*$ratingdata->rating; | $rating=$count*$ratingdata->rating; | ||
- | # echo "not enough data ($rating/$count)\n"; | + | #cycle older revisions looking for more ratings |
- | while($oldid=$wgTitle->getPreviousRevisionID($oldid)) | + | while($oldid=$wgTitle->getPreviousRevisionID($oldid)) |
{ | { | ||
- | # echo "trying previous ratings\n"; | ||
$ratingdata=getRatingData($oldid); | $ratingdata=getRatingData($oldid); | ||
+ | #If still not enough ratings | ||
if($count+$ratingdata->count<$countlimit) | if($count+$ratingdata->count<$countlimit) | ||
{ | { | ||
$count+=$ratingdata->count; | $count+=$ratingdata->count; | ||
$rating+=$ratingdata->count*$ratingdata->rating; | $rating+=$ratingdata->count*$ratingdata->rating; | ||
- | # echo "still not enough data ($rating/$count)\n"; | ||
} | } | ||
- | else | + | else #found enough ratings |
{ | { | ||
$rating+=($countlimit-$count)*$ratingdata->rating; | $rating+=($countlimit-$count)*$ratingdata->rating; | ||
$count=$countlimit; | $count=$countlimit; | ||
- | # echo "enough data ($rating/$count)\n"; | ||
$finalrating=$rating/$count; | $finalrating=$rating/$count; | ||
$oldid=false; | $oldid=false; | ||
Line 98: | Line 181: | ||
else | else | ||
$finalrating=$rating/$count; | $finalrating=$rating/$count; | ||
- | + | ||
+ | #format rating data | ||
if(is_numeric($finalrating)) | if(is_numeric($finalrating)) | ||
$finalrating=($finalrating-1)*1.25; | $finalrating=($finalrating-1)*1.25; | ||
- | $ratingarray=array('display'=>(is_numeric($finalrating)?number_format($finalrating, 2):$finalrating)." ($currentcount ratings)", | + | $ratingarray=array('display'=> |
+ | (is_numeric($finalrating)?number_format($finalrating, 2):$finalrating). | ||
+ | " ($currentcount ratings)", | ||
'count'=>$currentcount, | 'count'=>$currentcount, | ||
'rating'=>(is_numeric($finalrating)?$finalrating:0)); | 'rating'=>(is_numeric($finalrating)?$finalrating:0)); | ||
Line 107: | Line 193: | ||
} | } | ||
- | #Generate html code to insert into page | + | #------------------------------------------------------------------------------- |
+ | # Given the rating array and the page oldid, generate HTML code to be # | ||
+ | # displayed # | ||
+ | #------------------------------------------------------------------------------- | ||
function getRatingHTML($rating, $oldid) | function getRatingHTML($rating, $oldid) | ||
{ | { | ||
Line 113: | Line 202: | ||
$countlimit=3; | $countlimit=3; | ||
$html=''; | $html=''; | ||
+ | #generate stars | ||
for($x=0;$x<=4;$x++) | for($x=0;$x<=4;$x++) | ||
{ | { | ||
- | $html.='<a href="'.$wgTitle->getFullURL('oldid='.$oldid.'&rate='.($x+1)).'">'. | + | $html.='<a href="'. |
- | '<img src="'.$wgScriptPath.'/extensions/rating/star'; | + | $wgTitle->getFullURL('oldid='.$oldid.'&rate='.($x+1)).'">'. |
- | if($rating['rating']>=$x+1) | + | '<img src="?file=star'; |
+ | if($rating['rating']>=$x+1) #larger than current star : filled | ||
$html.='4'.($rating['count']<$countlimit?'b':''); | $html.='4'.($rating['count']<$countlimit?'b':''); | ||
- | elseif($rating['rating']>$x+0.75) | + | elseif($rating['rating']>$x+0.75) #3/4 current star : 3/4 filled |
$html.='3'.($rating['count']<$countlimit?'b':''); | $html.='3'.($rating['count']<$countlimit?'b':''); | ||
- | elseif($rating['rating']>$x+0.5) | + | elseif($rating['rating']>$x+0.5) #1/2 current star : 1/2 filled |
$html.='2'.($rating['count']<$countlimit?'b':''); | $html.='2'.($rating['count']<$countlimit?'b':''); | ||
- | elseif($rating['rating']>$x+0.25) | + | elseif($rating['rating']>$x+0.25) #1/4 current star : 1/4 filled |
$html.='1'.($rating['count']<$countlimit?'b':''); | $html.='1'.($rating['count']<$countlimit?'b':''); | ||
- | else | + | else #less than current star : empty |
$html.='0'; | $html.='0'; | ||
$html.='.png" align=bottom/></a>'."\n"; | $html.='.png" align=bottom/></a>'."\n"; | ||
} | } | ||
+ | #add text rating | ||
$html.=' '.$rating['display'].''; | $html.=' '.$rating['display'].''; | ||
$html=($rating['count']<$countlimit?'<b>'.$html.'</b>':$html); | $html=($rating['count']<$countlimit?'<b>'.$html.'</b>':$html); | ||
return $html; | return $html; | ||
- | } | ||
- | |||
- | #Insert rating to top of page | ||
- | function InsertRating($parserOutput, $text) { | ||
- | global $wgArticle; | ||
- | $oldid=getOldID($wgArticle); | ||
- | if($oldid) | ||
- | $text='<div id="ratingsection">'.getRatingHTML(getRating($oldid), $oldid).'</div>'.$text; | ||
- | } | ||
- | |||
- | |||
- | #set up extension info | ||
- | if(isset($wgScriptPath)) | ||
- | { | ||
- | $wgExtensionCredits["parserhook"][]=array( | ||
- | 'name' => 'Rating Extension', | ||
- | 'version' => '0.1', | ||
- | 'url' => 'http://wiki.peacocktech.com/wiki/RatingExtension', | ||
- | 'author' => '[http://about.peacocktech.com/trevorp/ Trevor Peacock]', | ||
- | 'description' => 'Adds rating mechanism' ); | ||
- | $wgHooks['OutputPageBeforeHTML'][] = 'InsertRating'; | ||
- | $wgHooks['SkinTemplateSetupPageCss'][] = 'RatingCss'; | ||
- | } | ||
- | |||
- | #Add CSS into skin for rating | ||
- | function RatingCss(&$css) { | ||
- | global $wgScriptPath; | ||
- | $css = "/*<![CDATA[*/". | ||
- | " @import \"$wgScriptPath/?file=rating.css\"; ". | ||
- | "/*]]>*/"; | ||
- | return true; | ||
} | } | ||
- | #Return file if requested | + | #------------------------------------------------------------------------------- |
+ | # Return a file and exit. # | ||
+ | # File determined by ?file= GET parameter # | ||
+ | #------------------------------------------------------------------------------- | ||
function doFile() | function doFile() | ||
{ | { | ||
switch ($_GET['file']) | switch ($_GET['file']) | ||
{ | { | ||
+ | #Star .png files | ||
+ | case "star0.png": | ||
+ | case "star1.png": | ||
+ | case "star1b.png": | ||
+ | case "star2.png": | ||
+ | case "star2b.png": | ||
+ | case "star3.png": | ||
+ | case "star3b.png": | ||
+ | case "star4.png": | ||
+ | case "star4b.png": | ||
+ | header("Content-type: image/png"); | ||
+ | echo readFile('extensions/rating/'.$_GET['file']); | ||
+ | die(); | ||
+ | #extension css styling | ||
case "rating.css": | case "rating.css": | ||
header("Content-type: text/css"); | header("Content-type: text/css"); | ||
Line 181: | Line 259: | ||
#ratingsection b { | #ratingsection b { | ||
- | // border: 1px solid black; | ||
color: red; | color: red; | ||
padding: 4px; | padding: 4px; |
Revision as of 04:34, 30 July 2006
<?php ################################################################################ # Core Code # ################################################################################ # This section handles the core functions of this extension # # * Serving Files # # * Recording Ratings # # * Displaying Ratings # ################################################################################ #------------------------------------------------------------------------------- # If html request requests file, serve file # # Files are requested by adding the ?file= GET parameter # #------------------------------------------------------------------------------- if(isset($_GET['file'])) doFile(); #------------------------------------------------------------------------------- # If html request contains rate information, process it # # Rating information indicated by ?rate= GET parameter # # # # MediaWiki engine is started by imitating the code in index.php # # This ensures database functions are working # #------------------------------------------------------------------------------- if(isset($_GET['rate'])) { #Init #---------------- require_once( 'includes/Setup.php' ); require_once( "includes/Wiki.php" ); $mediaWiki = new MediaWiki(); $action = $wgRequest->getVal( 'action', 'view' ); $title = $wgRequest->getVal( 'title' ); $wgTitle = $mediaWiki->checkInitialQueries($title, $action, $wgOut, $wgRequest, $wgContLang); #Record Rating #---------------- $sql = "REPLACE INTO `ratings` (`page_oldid`, `user_id`, `page_rating`) '. 'VALUES (".$_GET['oldid'].", '". ($wgUser->getID()?$wgUser->getID():$wgUser->getName()). "', ".$_GET['rate'].")"; $dbr =& wfGetDB( DB_WRITE ); $res=wfQuery($sql, DB_WRITE, ""); #Return to refering page and exit #---------------- $wgTitle->invalidateCache(); header( 'Location: '.$_SERVER["HTTP_REFERER"] ) ; die(); } #------------------------------------------------------------------------------- # Initialize extension # # Sets up credit information, and hooks # #------------------------------------------------------------------------------- if(isset($wgScriptPath)) { $wgExtensionCredits["parserhook"][]=array( 'name' => 'Rating Extension', 'version' => '0.1', 'url' => 'http://wiki.peacocktech.com/wiki/RatingExtension', 'author' => '[http://about.peacocktech.com/trevorp/ Trevor Peacock]', 'description' => 'Adds rating mechanism' ); $wgHooks['OutputPageBeforeHTML'][] = 'InsertRating'; $wgHooks['SkinTemplateSetupPageCss'][] = 'RatingCss'; } #------------------------------------------------------------------------------- # Insert rating to top of page # #------------------------------------------------------------------------------- function InsertRating($parserOutput, $text) { global $wgArticle; $oldid=getOldID($wgArticle); if($oldid) $text='<div id="ratingsection">'. getRatingHTML(getRating($oldid), $oldid).'</div>'.$text; } #------------------------------------------------------------------------------- # Add CSS into skin for rating # #------------------------------------------------------------------------------- function RatingCss(&$css) { global $wgScriptPath; $css = "/*<![CDATA[*/". " @import \"$wgScriptPath/?file=rating.css\"; ". "/*]]>*/"; return true; } ################################################################################ # Supporting Functions # ################################################################################ # These functions support the core functions of the extension # ################################################################################ #------------------------------------------------------------------------------- # Use the mediawiki engine to run the given sql code and return an object # # containing the first result of the query # #------------------------------------------------------------------------------- #run sql code function runQuery($sql) { $dbr =& wfGetDB( DB_SLAVE ); $res=wfQuery($sql, DB_SLAVE, ""); return $dbr->fetchObject( $res ); } #------------------------------------------------------------------------------- # Return the oldid of the current page # # If oldid=0 (most current revision) take the latest oldid from the database # # for the current article # #------------------------------------------------------------------------------- function getOldID($article) { $oldid=$article->getOldIDFromRequest(); if($oldid!=0) return $oldid; $dbr =& wfGetDB( DB_SLAVE ); $sql = "SELECT MAX(`rc_this_oldid`) AS `rc_this_oldid` FROM recentchanges '. 'WHERE rc_cur_id=".$article->getID().";"; $res=wfQuery($sql, DB_SLAVE, ""); $row=$dbr->fetchObject( $res ); if($row->rc_this_oldid) return $row->rc_this_oldid; return null; } #------------------------------------------------------------------------------- # Performs a SQL query to fetch a rating for page oldid # #------------------------------------------------------------------------------- function getRatingData($oldid) { $sql="SELECT COUNT(*) AS `count`, AVG(`page_rating`) AS `rating` '. 'FROM ratings WHERE `page_oldid`=".$oldid." GROUP BY `page_oldid`;"; return runQuery($sql); } #------------------------------------------------------------------------------- # Fetch and calculate a rating for page oldid # # If there are not enough ratings for the current revivion, cycle # # older revisions to gather a minimum number of ratings # #------------------------------------------------------------------------------- function getRating($oldid) { global $wgTitle; $countlimit=3; $ratingdata=getRatingData($oldid); $finalrating='?'; $currentcount=number_format($ratingdata->count, 0); #If there are not enough ratings for the current revision if($rating->count<$countlimit) { $count=$ratingdata->count; $rating=$count*$ratingdata->rating; #cycle older revisions looking for more ratings while($oldid=$wgTitle->getPreviousRevisionID($oldid)) { $ratingdata=getRatingData($oldid); #If still not enough ratings if($count+$ratingdata->count<$countlimit) { $count+=$ratingdata->count; $rating+=$ratingdata->count*$ratingdata->rating; } else #found enough ratings { $rating+=($countlimit-$count)*$ratingdata->rating; $count=$countlimit; $finalrating=$rating/$count; $oldid=false; } } } else $finalrating=$rating/$count; #format rating data if(is_numeric($finalrating)) $finalrating=($finalrating-1)*1.25; $ratingarray=array('display'=> (is_numeric($finalrating)?number_format($finalrating, 2):$finalrating). " ($currentcount ratings)", 'count'=>$currentcount, 'rating'=>(is_numeric($finalrating)?$finalrating:0)); return $ratingarray; } #------------------------------------------------------------------------------- # Given the rating array and the page oldid, generate HTML code to be # # displayed # #------------------------------------------------------------------------------- function getRatingHTML($rating, $oldid) { global $wgTitle, $wgScriptPath; $countlimit=3; $html=''; #generate stars for($x=0;$x<=4;$x++) { $html.='<a href="'. $wgTitle->getFullURL('oldid='.$oldid.'&rate='.($x+1)).'">'. '<img src="?file=star'; if($rating['rating']>=$x+1) #larger than current star : filled $html.='4'.($rating['count']<$countlimit?'b':''); elseif($rating['rating']>$x+0.75) #3/4 current star : 3/4 filled $html.='3'.($rating['count']<$countlimit?'b':''); elseif($rating['rating']>$x+0.5) #1/2 current star : 1/2 filled $html.='2'.($rating['count']<$countlimit?'b':''); elseif($rating['rating']>$x+0.25) #1/4 current star : 1/4 filled $html.='1'.($rating['count']<$countlimit?'b':''); else #less than current star : empty $html.='0'; $html.='.png" align=bottom/></a>'."\n"; } #add text rating $html.=' '.$rating['display'].''; $html=($rating['count']<$countlimit?'<b>'.$html.'</b>':$html); return $html; } #------------------------------------------------------------------------------- # Return a file and exit. # # File determined by ?file= GET parameter # #------------------------------------------------------------------------------- function doFile() { switch ($_GET['file']) { #Star .png files case "star0.png": case "star1.png": case "star1b.png": case "star2.png": case "star2b.png": case "star3.png": case "star3b.png": case "star4.png": case "star4b.png": header("Content-type: image/png"); echo readFile('extensions/rating/'.$_GET['file']); die(); #extension css styling case "rating.css": header("Content-type: text/css"); ?> #ratingsection { float: right; margin-top: -3.7em; padding: 3px; } #ratingsection b { color: red; padding: 4px; } <?php die(); } } ?>