RatingExtension/Source Code Dev
From PeacockWiki
(Difference between revisions)
Revision as of 03:53, 31 July 2006 (edit) 137.166.81.96 (Talk) ← Previous diff |
Revision as of 04:02, 31 July 2006 (edit) 137.166.81.96 (Talk) Next diff → |
||
Line 147: | Line 147: | ||
//TODO: Limit by namespace | //TODO: Limit by namespace | ||
global $wgArticle; | global $wgArticle; | ||
+ | # global $wgNamespaceNamesEn; | ||
+ | # var_dump($wgNamespaceNamesEn); | ||
+ | $allowedNamespaces=array( | ||
+ | 0=>true, //Default | ||
+ | 1=>true, //Talk | ||
+ | 2=>true, //User | ||
+ | 3=>true, //User_talk | ||
+ | 4=>true, //Mediawiki-1.7.1 | ||
+ | 5=>true, //Mediawiki-1.7.1_talk | ||
+ | 6=>true, //Image | ||
+ | 7=>true, //Image_talk | ||
+ | 8=>true, //MediaWiki | ||
+ | 9=>true, //MediaWiki_talk | ||
+ | 10=>true, //Template | ||
+ | 11=>true, //Template_talk | ||
+ | 12=>true, //Help | ||
+ | 13=>true, //Help_talk | ||
+ | 14=>true, //Category | ||
+ | 15=>true //Category_talk | ||
+ | ); | ||
+ | if(!$allowedNamespaces[$wgArticle->getTitle()->getNamespace()]) | ||
+ | return; | ||
$oldid=getOldID($wgArticle); | $oldid=getOldID($wgArticle); | ||
if($oldid) | if($oldid) |
Revision as of 04:02, 31 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'; $wgExtensionFunctions[] = "RatingExtension"; } function RatingExtension() { global $wgParser; $wgParser->setHook("rating", "renderRating"); $wgParser->setHook("ratingcount", "renderRatingCount"); $wgParser->setHook("ratings", "renderRatings"); } function renderWikiText($input, &$parser) { return $parser->parse($input, $parser->mTitle, $parser->mOptions, true, false)->getText(); } function getRatingFromTitle($title) { $title=Title::newFromText($title); if($title==null) return "NoArticle"; $oldid=getOldID(new Article($title)); if(!$oldid) return "NoOldID"; return getRating($oldid); } function renderRating($input, $argv, &$parser) { $rating=getRatingFromTitle($input); return $rating['rating']; } function renderRatingCount($input, $argv, &$parser) { $rating=getRatingFromTitle($input); return $rating['count']; } function getPageList($namespace=false) { $sql="SELECT `page_title` AS `title`, `page_namespace` AS `namespace`, `page_latest` AS `oldid` FROM `page`". ($namespace===false?"":'WHERE `page_namespace` IN ('.$namespace.')').';'; return runQuery2($sql); } function getRatingList($namespace=false) { global $wgNamespaceNamesEn; $articles=getPageList($namespace); $ratings=array(); foreach($articles as $article) { $rating=getRating($article->oldid); $ratings[]=array('article' => $wgNamespaceNamesEn[$article->namespace]. ($article->namespace==0?'':':').$article->title, 'rating' => $rating['rating'], 'count' => $rating['count']); } return $ratings; } function renderRatings($input, $argv, &$parser) { $ratings=getRatingList('0,1,2,3'); $output=''; foreach($ratings as $rating) { $output.=$rating['article'].' => '.$rating['rating']."\n\n"; } return renderWikiText(trim($output), $parser); } #------------------------------------------------------------------------------- # Insert rating to top of page # #------------------------------------------------------------------------------- function InsertRating($parserOutput, $text) { //TODO: Limit by namespace global $wgArticle; # global $wgNamespaceNamesEn; # var_dump($wgNamespaceNamesEn); $allowedNamespaces=array( 0=>true, //Default 1=>true, //Talk 2=>true, //User 3=>true, //User_talk 4=>true, //Mediawiki-1.7.1 5=>true, //Mediawiki-1.7.1_talk 6=>true, //Image 7=>true, //Image_talk 8=>true, //MediaWiki 9=>true, //MediaWiki_talk 10=>true, //Template 11=>true, //Template_talk 12=>true, //Help 13=>true, //Help_talk 14=>true, //Category 15=>true //Category_talk ); if(!$allowedNamespaces[$wgArticle->getTitle()->getNamespace()]) return; $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 # #------------------------------------------------------------------------------- function runQuery($sql) { $dbr =& wfGetDB( DB_SLAVE ); $res=wfQuery($sql, DB_SLAVE, ""); if(wfNumRows($res)>0) return $dbr->fetchObject( $res ); else return null; } function runQuery2($sql) { $dbr =& wfGetDB( DB_SLAVE ); $res=wfQuery($sql, DB_SLAVE, ""); $array=array(); while($item=$dbr->fetchObject( $res )) $array[]=$item; return $array; } #------------------------------------------------------------------------------- # 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 `oldid` FROM recentchanges ". # "WHERE rc_cur_id=".$article->getID().";"; $sql="SELECT `page_latest` AS `oldid` FROM `page` ". "WHERE `page_id`=".$article->getID().";"; $res=wfQuery($sql, DB_SLAVE, ""); $row=$dbr->fetchObject( $res ); if($row->oldid) return $row->oldid; return null; } function getArticle($article) { $dbr =& wfGetDB( DB_SLAVE ); $sql = "SELECT * FROM page ". "WHERE page_title=\"".$article."\";"; $res=wfQuery($sql, DB_SLAVE, ""); $row=$dbr->fetchObject( $res ); return $row; } #------------------------------------------------------------------------------- # 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); } function getPreviousRevisionID( $revision ) { $dbr =& wfGetDB( DB_SLAVE ); return $dbr->selectField( 'revision', 'rev_id', 'rev_page=(SELECT `rev_page` from `revision` WHERE `rev_id`='. intval( $revision ).')'.' AND rev_id<' . intval( $revision ) . ' ORDER BY rev_id DESC' ); } #------------------------------------------------------------------------------- # 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); # var_dump($ratingdata); $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=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)); # var_dump($ratingarray); 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(); } } ?>