RatingExtension/Source Code Dev
From PeacockWiki
(Difference between revisions)
Revision as of 02:27, 31 July 2006 (edit) Trevorp (Talk | contribs) ← Previous diff |
Current revision (07:08, 1 August 2006) (edit) 137.166.81.96 (Talk) |
||
Line 1: | Line 1: | ||
<pre><?php | <pre><?php | ||
+ | |||
+ | ################################################################################ | ||
+ | # Setup # | ||
+ | ################################################################################ | ||
+ | # This section defines parameters of the plugin # | ||
+ | ################################################################################ | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Sets the minimum number of ratings that can be returned in a ratings tag # | ||
+ | # This helps keep performance for large wikis acceptable # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | $renderLimit=100; | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Sets the minimum number of ratings required for the rating to be valid # | ||
+ | # If the number of ratings are less, rating is 0 and bolded # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | $countLimit=3; | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Defines namespaces for which ratings are enabled # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | $allowedNamespaces=array( | ||
+ | 0=>true, //Default | ||
+ | 1=>true, //Talk | ||
+ | 2=>true, //User | ||
+ | 3=>true, //User_talk | ||
+ | 4=>true, //Project | ||
+ | 5=>true, //Project_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 | ||
+ | ); | ||
################################################################################ | ################################################################################ | ||
Line 39: | Line 79: | ||
#Record Rating | #Record Rating | ||
#---------------- | #---------------- | ||
+ | $dbr =& wfGetDB( DB_WRITE ); | ||
$sql = "REPLACE INTO `ratings` (`page_oldid`, `user_id`, `page_rating`) ". | $sql = "REPLACE INTO `ratings` (`page_oldid`, `user_id`, `page_rating`) ". | ||
- | "VALUES (".$_GET['oldid'].", '". | + | "VALUES (".intval($_GET['oldid']).", '". |
($wgUser->getID()?$wgUser->getID():$wgUser->getName()). | ($wgUser->getID()?$wgUser->getID():$wgUser->getName()). | ||
- | "', ".$_GET['rate'].")"; | + | "', ".intval($_GET['rate']).")"; |
- | $dbr =& wfGetDB( DB_WRITE ); | + | |
$res=wfQuery($sql, DB_WRITE, ""); | $res=wfQuery($sql, DB_WRITE, ""); | ||
+ | |||
+ | calculateRating($_GET['oldid']); | ||
#Return to refering page and exit | #Return to refering page and exit | ||
#---------------- | #---------------- | ||
$wgTitle->invalidateCache(); | $wgTitle->invalidateCache(); | ||
+ | $dbr->immediateCommit(); | ||
header( 'Location: '.$_SERVER["HTTP_REFERER"] ) ; | header( 'Location: '.$_SERVER["HTTP_REFERER"] ) ; | ||
die(); | die(); | ||
Line 59: | Line 102: | ||
if(isset($wgScriptPath)) | if(isset($wgScriptPath)) | ||
{ | { | ||
- | $wgExtensionCredits["parserhook"][]=array( | + | $wgExtensionCredits["parserhook"][]=array( |
- | 'name' => 'Rating Extension', | + | 'name' => 'Rating Extension', |
- | 'version' => '0.1', | + | 'version' => '0.3', |
- | 'url' => 'http://wiki.peacocktech.com/wiki/RatingExtension', | + | 'url' => 'http://wiki.peacocktech.com/wiki/RatingExtension', |
- | 'author' => '[http://about.peacocktech.com/trevorp/ Trevor Peacock]', | + | 'author' => '[http://about.peacocktech.com/trevorp/ Trevor Peacock]', |
- | 'description' => 'Adds rating mechanism' ); | + | 'description' => 'Adds rating mechanism' ); |
$wgHooks['OutputPageBeforeHTML'][] = 'InsertRating'; | $wgHooks['OutputPageBeforeHTML'][] = 'InsertRating'; | ||
$wgHooks['SkinTemplateSetupPageCss'][] = 'RatingCss'; | $wgHooks['SkinTemplateSetupPageCss'][] = 'RatingCss'; | ||
Line 78: | Line 121: | ||
} | } | ||
- | function renderWikiText($input, &$parser) | + | #------------------------------------------------------------------------------- |
- | { | + | # Render the <rating> tag # |
- | return $parser->parse($input, $parser->mTitle, $parser->mOptions, | + | # Shows the rating of the page specified by the text between the tags # |
- | 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) | function renderRating($input, $argv, &$parser) | ||
{ | { | ||
- | $rating=getRatingFromTitle($input); | + | $rating=getRatingCache(getOldIDFromTitle(trim($input))); |
- | return $rating['rating']; | + | return number_format($rating['rating'], 2); |
} | } | ||
+ | #------------------------------------------------------------------------------- | ||
+ | # Render the <rating> tag # | ||
+ | # Shows the number of ratings of the page specified by the text between # | ||
+ | # the tags # | ||
+ | #------------------------------------------------------------------------------- | ||
function renderRatingCount($input, $argv, &$parser) | function renderRatingCount($input, $argv, &$parser) | ||
{ | { | ||
- | $rating=getRatingFromTitle($input); | + | $rating=getRatingCache(getOldIDFromTitle(trim($input))); |
- | return $rating['count']; | + | return number_format($rating['count'], 2); |
- | } | + | |
- | + | ||
- | 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; | + | |
} | } | ||
+ | #------------------------------------------------------------------------------- | ||
+ | # Displays a list of ratings based on the parameters given between the tags # | ||
+ | #------------------------------------------------------------------------------- | ||
function renderRatings($input, $argv, &$parser) | function renderRatings($input, $argv, &$parser) | ||
{ | { | ||
- | $ratings=getRatingList('0,1,2,3'); | + | $parameters=splitParameters($input); |
+ | $sortdata=getSortData(isset($parameters['namespace'])?$parameters['namespace']:array()); | ||
+ | $ratings=getRatingList( | ||
+ | isset($parameters['namespace'])?$parameters['namespace']:array(), $sortdata['column'], $sortdata['order'], isset($parameters['limit'])?$parameters['limit'][0]:10); | ||
$output=''; | $output=''; | ||
+ | $displayCount=(isset($parameters['displaycount'])? | ||
+ | $parameters['displaycount'][0]:'false')!='false'; | ||
+ | $displayRating=(isset($parameters['displayrating'])? | ||
+ | $parameters['displayrating'][0]:'true')!='false'; | ||
+ | $pattern=isset($parameters['pattern'])?$parameters['pattern'][0]: | ||
+ | '[[$1|$2]]'.($displayRating?' ($3)':'').($displayCount?' ($4 ratings)':''); | ||
+ | $limit=isset($parameters['limit'])?$parameters['limit'][0]:10; | ||
foreach($ratings as $rating) | foreach($ratings as $rating) | ||
{ | { | ||
- | $output.=$rating['article'].' => '.$rating['rating']."\n\n"; | + | $output.=str_replace(array('$1', '$2', '$3', '$4', '$5'), |
+ | array($rating['title'], strtr($rating['title'], '_', ' '), | ||
+ | number_format($rating['rating'], 2), | ||
+ | $rating['count'], $rating['oldid']), $pattern)."\n\n"; | ||
+ | if(--$limit==0) break; | ||
} | } | ||
return renderWikiText(trim($output), $parser); | return renderWikiText(trim($output), $parser); | ||
Line 145: | Line 174: | ||
#------------------------------------------------------------------------------- | #------------------------------------------------------------------------------- | ||
function InsertRating($parserOutput, $text) { | function InsertRating($parserOutput, $text) { | ||
- | //TODO: Fix getOldID to get ALL articles (without revisions) | + | global $wgArticle, $allowedNamespaces; |
- | //TODO: Limit by namespace | + | if(!$allowedNamespaces[$wgArticle->getTitle()->getNamespace()]) |
- | global $wgArticle; | + | return; |
$oldid=getOldID($wgArticle); | $oldid=getOldID($wgArticle); | ||
if($oldid) | if($oldid) | ||
$text='<div id="ratingsection">'. | $text='<div id="ratingsection">'. | ||
- | getRatingHTML(getRating($oldid), $oldid).'</div>'.$text; | + | getRatingHTML(getRatingCache($oldid), $oldid).'</div>'.$text; |
} | } | ||
Line 170: | Line 199: | ||
# These functions support the core functions of the extension # | # These functions support the core functions of the extension # | ||
################################################################################ | ################################################################################ | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Processes sortby parameters to determine how to sort ratings # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function getSortData($sort) | ||
+ | { | ||
+ | $column='rating'; | ||
+ | $order=-1; | ||
+ | foreach($sort as $item) | ||
+ | { | ||
+ | switch($item) | ||
+ | { | ||
+ | case 'rating': | ||
+ | $column='rating'; break; | ||
+ | case 'name': | ||
+ | $column='title'; break; | ||
+ | case 'count': | ||
+ | $column='count'; break; | ||
+ | case 'ascending': | ||
+ | $order=SORT_ASC; break; | ||
+ | case 'descending': | ||
+ | $order=SORT_DESC; break; | ||
+ | } | ||
+ | } | ||
+ | if($order==-1) | ||
+ | { | ||
+ | switch($column) | ||
+ | { | ||
+ | case 'rating': | ||
+ | $order=SORT_DESC; break; | ||
+ | case 'title': | ||
+ | $order=SORT_ASC; break; | ||
+ | case 'count': | ||
+ | $order=SORT_DESC; break; | ||
+ | default: | ||
+ | $order=SORT_DESC; | ||
+ | } | ||
+ | } | ||
+ | return array('column'=>$column, 'order'=>$order); | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Processes the given text using the mediawiki parser engine # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function renderWikiText($input, &$parser) | ||
+ | { | ||
+ | return $parser->parse($input, $parser->mTitle, $parser->mOptions, | ||
+ | false, false)->getText(); | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Returns the page rating given the pages string title # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function getOldIDFromTitle($title) | ||
+ | { | ||
+ | $title=Title::newFromText($title); | ||
+ | if($title==null) | ||
+ | { | ||
+ | echo "NoArticle"; | ||
+ | return 0; | ||
+ | } | ||
+ | $oldid=getOldID(new Article($title)); | ||
+ | if(!$oldid) | ||
+ | { | ||
+ | return "NoOldID"; | ||
+ | return 0; | ||
+ | } | ||
+ | return $oldid; | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Completes ratings_cache table for any revisions without ratings # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function doFillCache() | ||
+ | { | ||
+ | global $allowedNamespaces; | ||
+ | $namespacestring=''; | ||
+ | foreach(array_keys($allowedNamespaces) as $space) | ||
+ | { | ||
+ | if(is_numeric($space)) | ||
+ | { | ||
+ | $namespacestring.=', '.$space; | ||
+ | } | ||
+ | } | ||
+ | $namespacestring=substr($namespacestring, 2); | ||
+ | $sql="SELECT `page_latest` AS `oldid` FROM `page` WHERE".($filterByNamespace? | ||
+ | ' `page_namespace` IN ('.$namespacestring.') AND':"").' `page_latest` NOT IN (SELECT `page_oldid` FROM `ratings_cache`);'; | ||
+ | $articles=runQuery2($sql); | ||
+ | foreach($articles as $article) | ||
+ | getRating($article->oldid); | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Returns a list of pages in the specified namespaces # | ||
+ | # Optionally it may return sorting rating information for results # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function getPageList($namespace=array(), $ratings=false, $sort='title', $order=SORT_ASC, $limit=100) | ||
+ | { | ||
+ | global $renderLimit, $allowedNamespaces; | ||
+ | $limit=($limit>$renderLimit?$renderLimit:$limit); | ||
+ | $namespacestring=''; | ||
+ | $filterByNamespace=false; | ||
+ | foreach($namespace as $space) | ||
+ | { | ||
+ | if(is_numeric($space) && isset($allowedNamespaces[$space])) | ||
+ | { | ||
+ | $namespacestring.=', '.$space; | ||
+ | $filterByNamespace=true; | ||
+ | } | ||
+ | } | ||
+ | if($filterByNamespace) | ||
+ | $namespacestring=substr($namespacestring, 2); | ||
+ | $sql="SELECT `page_title` AS `title`, `page_namespace` AS `namespace`, | ||
+ | `page_latest` AS `oldid` FROM `page`".($filterByNamespace? | ||
+ | ' WHERE `page_namespace` IN ('.$namespacestring.')':"").';'; | ||
+ | if($ratings) | ||
+ | $sql="SELECT `page_title` AS `title`, `page_namespace` AS `namespace`, ". | ||
+ | "`page_latest` AS `oldid`, `page_oldid`, `page_rating` AS `rating`, `page_rating_count` AS `count` FROM `page`, `ratings_cache` WHERE `page_latest`=`page_oldid`".($filterByNamespace? | ||
+ | ' AND `page_namespace` IN ('.$namespacestring.')':""). | ||
+ | ' ORDER BY '.$sort.($order==SORT_ASC?'':'').($order==SORT_DESC?' DESC':'').' LIMIT '.$limit.';'; | ||
+ | return runQuery2($sql); | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Returns a list of pages and their ratings for all pages in the specified # | ||
+ | # namespaces # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function getRatingList($namespace=array(), $sort='title', $order=SORT_ASC, $limit=100) | ||
+ | { | ||
+ | global $wgNamespaceNamesEn, $renderLimit; | ||
+ | doFillCache(); | ||
+ | $limit=($limit>$renderLimit?$renderLimit:$limit); | ||
+ | $articles=getPageList($namespace, true, $sort, $order, $limit); | ||
+ | $ratings=array(); | ||
+ | foreach($articles as $article) | ||
+ | { | ||
+ | $rating=formatRating(array('count'=>$article->count, 'rating'=>$article->rating)); | ||
+ | $ratings[]=array('title' => $wgNamespaceNamesEn[$article->namespace]. | ||
+ | ($article->namespace==0?'':':').$article->title, | ||
+ | 'rating' => $rating['rating'], 'count' => $rating['count'], 'oldid'=>$article->oldid); | ||
+ | } | ||
+ | return $ratings; | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Splits parameters from the wikitext. # | ||
+ | # Each parameter should be on its own line in the format parameter = value # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function splitParameters($input) | ||
+ | { | ||
+ | $parameters=array(); | ||
+ | foreach(split("\n", $input) as $parameter) | ||
+ | { | ||
+ | $parameter=split('=', $parameter, 2); | ||
+ | if(count($parameter)==2) | ||
+ | { | ||
+ | foreach($parameter as $key => $val) | ||
+ | $parameter[$key]=trim($val); | ||
+ | if(isset($parameters[$parameter[0]])) | ||
+ | $parameters[$parameter[0]][]=$parameter[1]; | ||
+ | else | ||
+ | $parameters[$parameter[0]]=array($parameter[1]); | ||
+ | } | ||
+ | } | ||
+ | return $parameters; | ||
+ | } | ||
#------------------------------------------------------------------------------- | #------------------------------------------------------------------------------- | ||
Line 206: | Line 401: | ||
return $oldid; | return $oldid; | ||
$dbr =& wfGetDB( DB_SLAVE ); | $dbr =& wfGetDB( DB_SLAVE ); | ||
- | $sql = "SELECT MAX(`rc_this_oldid`) AS `rc_this_oldid` FROM recentchanges ". | + | $sql="SELECT `page_latest` AS `oldid` FROM `page` ". |
- | "WHERE rc_cur_id=".$article->getID().";"; | + | "WHERE `page_id`=".$article->getID().";"; |
$res=wfQuery($sql, DB_SLAVE, ""); | $res=wfQuery($sql, DB_SLAVE, ""); | ||
$row=$dbr->fetchObject( $res ); | $row=$dbr->fetchObject( $res ); | ||
- | if($row->rc_this_oldid) | + | if($row->oldid) |
- | return $row->rc_this_oldid; | + | return $row->oldid; |
return null; | 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; | ||
} | } | ||
Line 231: | Line 416: | ||
{ | { | ||
$sql="SELECT COUNT(*) AS `count`, AVG(`page_rating`) AS `rating` ". | $sql="SELECT COUNT(*) AS `count`, AVG(`page_rating`) AS `rating` ". | ||
- | "FROM ratings WHERE `page_oldid`=".$oldid." GROUP BY `page_oldid`;"; | + | "FROM ratings WHERE `page_oldid`=".intval($oldid)." GROUP BY `page_oldid`;"; |
return runQuery($sql); | return runQuery($sql); | ||
} | } | ||
+ | #------------------------------------------------------------------------------- | ||
+ | # Returns the ID for the revision before $revision # | ||
+ | #------------------------------------------------------------------------------- | ||
function getPreviousRevisionID( $revision ) { | function getPreviousRevisionID( $revision ) { | ||
$dbr =& wfGetDB( DB_SLAVE ); | $dbr =& wfGetDB( DB_SLAVE ); | ||
Line 247: | Line 435: | ||
# If there are not enough ratings for the current revivion, cycle # | # If there are not enough ratings for the current revivion, cycle # | ||
# older revisions to gather a minimum number of ratings # | # older revisions to gather a minimum number of ratings # | ||
+ | # Updates cache table with calcaulated values # | ||
#------------------------------------------------------------------------------- | #------------------------------------------------------------------------------- | ||
- | function getRating($oldid) | + | function calculateRating($oldid) |
{ | { | ||
- | global $wgTitle; | + | global $wgTitle, $countLimit; |
- | + | $origid=$oldid; | |
- | $countlimit=3; | + | |
- | + | ||
$ratingdata=getRatingData($oldid); | $ratingdata=getRatingData($oldid); | ||
- | # var_dump($ratingdata); | ||
$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 there are not enough ratings for the current revision | ||
- | if($rating->count<$countlimit) | + | if($ratingdata->count<$countLimit) |
{ | { | ||
$count=$ratingdata->count; | $count=$ratingdata->count; | ||
Line 268: | Line 454: | ||
$ratingdata=getRatingData($oldid); | $ratingdata=getRatingData($oldid); | ||
#If still not enough ratings | #If still not enough ratings | ||
- | if($count+$ratingdata->count<$countlimit) | + | if($count+$ratingdata->count<$countLimit) |
{ | { | ||
$count+=$ratingdata->count; | $count+=$ratingdata->count; | ||
Line 275: | Line 461: | ||
else #found enough ratings | else #found enough ratings | ||
{ | { | ||
- | $rating+=($countlimit-$count)*$ratingdata->rating; | + | $rating+=($countLimit-$count)*$ratingdata->rating; |
- | $count=$countlimit; | + | $count=$countLimit; |
$finalrating=$rating/$count; | $finalrating=$rating/$count; | ||
$oldid=false; | $oldid=false; | ||
Line 283: | Line 469: | ||
} | } | ||
else | else | ||
- | $finalrating=$rating/$count; | + | $finalrating=$ratingdata->rating; |
+ | $dbr =& wfGetDB( DB_WRITE ); | ||
+ | $sql = "REPLACE INTO `ratings_cache` (`page_oldid`, `page_rating`, ". | ||
+ | "`page_rating_count`) VALUES (".intval($origid).", ". | ||
+ | (is_numeric($finalrating)?$finalrating:0).", ".$currentcount.")"; | ||
+ | $res=wfQuery($sql, DB_WRITE, ""); | ||
+ | |||
+ | return array('rating'=>$finalrating, 'count'=>$currentcount); | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Formats rating array for insertion to page rating section # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function formatRating($rating) | ||
+ | { | ||
+ | $finalrating=$rating['rating']; | ||
+ | $currentcount=$rating['count']; | ||
+ | |||
#format rating data | #format rating data | ||
- | if(is_numeric($finalrating)) | + | if(is_numeric($finalrating) && $finalrating>0) |
$finalrating=($finalrating-1)*1.25; | $finalrating=($finalrating-1)*1.25; | ||
$ratingarray=array('display'=> | $ratingarray=array('display'=> | ||
Line 293: | Line 496: | ||
'count'=>$currentcount, | 'count'=>$currentcount, | ||
'rating'=>(is_numeric($finalrating)?$finalrating:0)); | 'rating'=>(is_numeric($finalrating)?$finalrating:0)); | ||
- | # var_dump($ratingarray); | ||
return $ratingarray; | return $ratingarray; | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Calculates rating from database for specified revision # | ||
+ | # Updates rating cache table # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function getRating($oldid) | ||
+ | { | ||
+ | return formatRating(calculateRating($oldid)); | ||
+ | } | ||
+ | |||
+ | #------------------------------------------------------------------------------- | ||
+ | # Fetches the ratings from cache table # | ||
+ | # Calculates rating if it is not found in cache # | ||
+ | #------------------------------------------------------------------------------- | ||
+ | function getRatingCache($oldid) | ||
+ | { | ||
+ | $sql='SELECT * FROM `ratings_cache` WHERE `page_oldid`='.intval($oldid).';'; | ||
+ | $rating=runQuery($sql); | ||
+ | $rating=array('rating'=>$rating->page_rating, 'count'=>$rating->age_rating_count); | ||
+ | if($rating->page_oldid==null) | ||
+ | $rating=calculateRating($oldid); | ||
+ | return formatRating($rating); | ||
} | } | ||
Line 303: | Line 528: | ||
function getRatingHTML($rating, $oldid) | function getRatingHTML($rating, $oldid) | ||
{ | { | ||
- | global $wgTitle, $wgScriptPath; | + | global $wgTitle, $wgScriptPath, $countLimit; |
- | $countlimit=3; | + | |
$html=''; | $html=''; | ||
#generate stars | #generate stars | ||
Line 310: | Line 534: | ||
{ | { | ||
$html.='<a href="'. | $html.='<a href="'. | ||
- | $wgTitle->getFullURL('oldid='.$oldid.'&rate='.($x+1)).'">'. | + | $wgTitle->getFullURL('oldid='.$oldid.'&rate='.($x+1)).'" rel="nofollow">'. |
- | '<img src="?file=star'; | + | '<img src="?file=Star'; |
if($rating['rating']>=$x+1) #larger than current star : filled | 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) #3/4 current star : 3/4 filled | + | 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) #1/2 current star : 1/2 filled | + | 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) #1/4 current star : 1/4 filled | + | 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 #less than current star : empty | else #less than current star : empty | ||
$html.='0'; | $html.='0'; | ||
Line 326: | Line 550: | ||
#add text rating | #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; | ||
} | } | ||
Line 340: | Line 564: | ||
{ | { | ||
#Star .png files | #Star .png files | ||
- | case "star0.png": | + | case "Star0.png": |
- | case "star1.png": | + | case "Star1.png": |
- | case "star1b.png": | + | case "Star1b.png": |
- | case "star2.png": | + | case "Star2.png": |
- | case "star2b.png": | + | case "Star2b.png": |
- | case "star3.png": | + | case "Star3.png": |
- | case "star3b.png": | + | case "Star3b.png": |
- | case "star4.png": | + | case "Star4.png": |
- | case "star4b.png": | + | case "Star4b.png": |
header("Content-type: image/png"); | header("Content-type: image/png"); | ||
echo readFile('extensions/rating/'.$_GET['file']); | echo readFile('extensions/rating/'.$_GET['file']); |
Current revision
<?php ################################################################################ # Setup # ################################################################################ # This section defines parameters of the plugin # ################################################################################ #------------------------------------------------------------------------------- # Sets the minimum number of ratings that can be returned in a ratings tag # # This helps keep performance for large wikis acceptable # #------------------------------------------------------------------------------- $renderLimit=100; #------------------------------------------------------------------------------- # Sets the minimum number of ratings required for the rating to be valid # # If the number of ratings are less, rating is 0 and bolded # #------------------------------------------------------------------------------- $countLimit=3; #------------------------------------------------------------------------------- # Defines namespaces for which ratings are enabled # #------------------------------------------------------------------------------- $allowedNamespaces=array( 0=>true, //Default 1=>true, //Talk 2=>true, //User 3=>true, //User_talk 4=>true, //Project 5=>true, //Project_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 ); ################################################################################ # 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 #---------------- $dbr =& wfGetDB( DB_WRITE ); $sql = "REPLACE INTO `ratings` (`page_oldid`, `user_id`, `page_rating`) ". "VALUES (".intval($_GET['oldid']).", '". ($wgUser->getID()?$wgUser->getID():$wgUser->getName()). "', ".intval($_GET['rate']).")"; $res=wfQuery($sql, DB_WRITE, ""); calculateRating($_GET['oldid']); #Return to refering page and exit #---------------- $wgTitle->invalidateCache(); $dbr->immediateCommit(); 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.3', '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"); } #------------------------------------------------------------------------------- # Render the <rating> tag # # Shows the rating of the page specified by the text between the tags # #------------------------------------------------------------------------------- function renderRating($input, $argv, &$parser) { $rating=getRatingCache(getOldIDFromTitle(trim($input))); return number_format($rating['rating'], 2); } #------------------------------------------------------------------------------- # Render the <rating> tag # # Shows the number of ratings of the page specified by the text between # # the tags # #------------------------------------------------------------------------------- function renderRatingCount($input, $argv, &$parser) { $rating=getRatingCache(getOldIDFromTitle(trim($input))); return number_format($rating['count'], 2); } #------------------------------------------------------------------------------- # Displays a list of ratings based on the parameters given between the tags # #------------------------------------------------------------------------------- function renderRatings($input, $argv, &$parser) { $parameters=splitParameters($input); $sortdata=getSortData(isset($parameters['namespace'])?$parameters['namespace']:array()); $ratings=getRatingList( isset($parameters['namespace'])?$parameters['namespace']:array(), $sortdata['column'], $sortdata['order'], isset($parameters['limit'])?$parameters['limit'][0]:10); $output=''; $displayCount=(isset($parameters['displaycount'])? $parameters['displaycount'][0]:'false')!='false'; $displayRating=(isset($parameters['displayrating'])? $parameters['displayrating'][0]:'true')!='false'; $pattern=isset($parameters['pattern'])?$parameters['pattern'][0]: '[[$1|$2]]'.($displayRating?' ($3)':'').($displayCount?' ($4 ratings)':''); $limit=isset($parameters['limit'])?$parameters['limit'][0]:10; foreach($ratings as $rating) { $output.=str_replace(array('$1', '$2', '$3', '$4', '$5'), array($rating['title'], strtr($rating['title'], '_', ' '), number_format($rating['rating'], 2), $rating['count'], $rating['oldid']), $pattern)."\n\n"; if(--$limit==0) break; } return renderWikiText(trim($output), $parser); } #------------------------------------------------------------------------------- # Insert rating to top of page # #------------------------------------------------------------------------------- function InsertRating($parserOutput, $text) { global $wgArticle, $allowedNamespaces; if(!$allowedNamespaces[$wgArticle->getTitle()->getNamespace()]) return; $oldid=getOldID($wgArticle); if($oldid) $text='<div id="ratingsection">'. getRatingHTML(getRatingCache($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 # ################################################################################ #------------------------------------------------------------------------------- # Processes sortby parameters to determine how to sort ratings # #------------------------------------------------------------------------------- function getSortData($sort) { $column='rating'; $order=-1; foreach($sort as $item) { switch($item) { case 'rating': $column='rating'; break; case 'name': $column='title'; break; case 'count': $column='count'; break; case 'ascending': $order=SORT_ASC; break; case 'descending': $order=SORT_DESC; break; } } if($order==-1) { switch($column) { case 'rating': $order=SORT_DESC; break; case 'title': $order=SORT_ASC; break; case 'count': $order=SORT_DESC; break; default: $order=SORT_DESC; } } return array('column'=>$column, 'order'=>$order); } #------------------------------------------------------------------------------- # Processes the given text using the mediawiki parser engine # #------------------------------------------------------------------------------- function renderWikiText($input, &$parser) { return $parser->parse($input, $parser->mTitle, $parser->mOptions, false, false)->getText(); } #------------------------------------------------------------------------------- # Returns the page rating given the pages string title # #------------------------------------------------------------------------------- function getOldIDFromTitle($title) { $title=Title::newFromText($title); if($title==null) { echo "NoArticle"; return 0; } $oldid=getOldID(new Article($title)); if(!$oldid) { return "NoOldID"; return 0; } return $oldid; } #------------------------------------------------------------------------------- # Completes ratings_cache table for any revisions without ratings # #------------------------------------------------------------------------------- function doFillCache() { global $allowedNamespaces; $namespacestring=''; foreach(array_keys($allowedNamespaces) as $space) { if(is_numeric($space)) { $namespacestring.=', '.$space; } } $namespacestring=substr($namespacestring, 2); $sql="SELECT `page_latest` AS `oldid` FROM `page` WHERE".($filterByNamespace? ' `page_namespace` IN ('.$namespacestring.') AND':"").' `page_latest` NOT IN (SELECT `page_oldid` FROM `ratings_cache`);'; $articles=runQuery2($sql); foreach($articles as $article) getRating($article->oldid); } #------------------------------------------------------------------------------- # Returns a list of pages in the specified namespaces # # Optionally it may return sorting rating information for results # #------------------------------------------------------------------------------- function getPageList($namespace=array(), $ratings=false, $sort='title', $order=SORT_ASC, $limit=100) { global $renderLimit, $allowedNamespaces; $limit=($limit>$renderLimit?$renderLimit:$limit); $namespacestring=''; $filterByNamespace=false; foreach($namespace as $space) { if(is_numeric($space) && isset($allowedNamespaces[$space])) { $namespacestring.=', '.$space; $filterByNamespace=true; } } if($filterByNamespace) $namespacestring=substr($namespacestring, 2); $sql="SELECT `page_title` AS `title`, `page_namespace` AS `namespace`, `page_latest` AS `oldid` FROM `page`".($filterByNamespace? ' WHERE `page_namespace` IN ('.$namespacestring.')':"").';'; if($ratings) $sql="SELECT `page_title` AS `title`, `page_namespace` AS `namespace`, ". "`page_latest` AS `oldid`, `page_oldid`, `page_rating` AS `rating`, `page_rating_count` AS `count` FROM `page`, `ratings_cache` WHERE `page_latest`=`page_oldid`".($filterByNamespace? ' AND `page_namespace` IN ('.$namespacestring.')':""). ' ORDER BY '.$sort.($order==SORT_ASC?'':'').($order==SORT_DESC?' DESC':'').' LIMIT '.$limit.';'; return runQuery2($sql); } #------------------------------------------------------------------------------- # Returns a list of pages and their ratings for all pages in the specified # # namespaces # #------------------------------------------------------------------------------- function getRatingList($namespace=array(), $sort='title', $order=SORT_ASC, $limit=100) { global $wgNamespaceNamesEn, $renderLimit; doFillCache(); $limit=($limit>$renderLimit?$renderLimit:$limit); $articles=getPageList($namespace, true, $sort, $order, $limit); $ratings=array(); foreach($articles as $article) { $rating=formatRating(array('count'=>$article->count, 'rating'=>$article->rating)); $ratings[]=array('title' => $wgNamespaceNamesEn[$article->namespace]. ($article->namespace==0?'':':').$article->title, 'rating' => $rating['rating'], 'count' => $rating['count'], 'oldid'=>$article->oldid); } return $ratings; } #------------------------------------------------------------------------------- # Splits parameters from the wikitext. # # Each parameter should be on its own line in the format parameter = value # #------------------------------------------------------------------------------- function splitParameters($input) { $parameters=array(); foreach(split("\n", $input) as $parameter) { $parameter=split('=', $parameter, 2); if(count($parameter)==2) { foreach($parameter as $key => $val) $parameter[$key]=trim($val); if(isset($parameters[$parameter[0]])) $parameters[$parameter[0]][]=$parameter[1]; else $parameters[$parameter[0]]=array($parameter[1]); } } return $parameters; } #------------------------------------------------------------------------------- # 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 `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; } #------------------------------------------------------------------------------- # 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`=".intval($oldid)." GROUP BY `page_oldid`;"; return runQuery($sql); } #------------------------------------------------------------------------------- # Returns the ID for the revision before $revision # #------------------------------------------------------------------------------- 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 # # Updates cache table with calcaulated values # #------------------------------------------------------------------------------- function calculateRating($oldid) { global $wgTitle, $countLimit; $origid=$oldid; $ratingdata=getRatingData($oldid); $finalrating='?'; $currentcount=number_format($ratingdata->count, 0); #If there are not enough ratings for the current revision if($ratingdata->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=$ratingdata->rating; $dbr =& wfGetDB( DB_WRITE ); $sql = "REPLACE INTO `ratings_cache` (`page_oldid`, `page_rating`, ". "`page_rating_count`) VALUES (".intval($origid).", ". (is_numeric($finalrating)?$finalrating:0).", ".$currentcount.")"; $res=wfQuery($sql, DB_WRITE, ""); return array('rating'=>$finalrating, 'count'=>$currentcount); } #------------------------------------------------------------------------------- # Formats rating array for insertion to page rating section # #------------------------------------------------------------------------------- function formatRating($rating) { $finalrating=$rating['rating']; $currentcount=$rating['count']; #format rating data if(is_numeric($finalrating) && $finalrating>0) $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; } #------------------------------------------------------------------------------- # Calculates rating from database for specified revision # # Updates rating cache table # #------------------------------------------------------------------------------- function getRating($oldid) { return formatRating(calculateRating($oldid)); } #------------------------------------------------------------------------------- # Fetches the ratings from cache table # # Calculates rating if it is not found in cache # #------------------------------------------------------------------------------- function getRatingCache($oldid) { $sql='SELECT * FROM `ratings_cache` WHERE `page_oldid`='.intval($oldid).';'; $rating=runQuery($sql); $rating=array('rating'=>$rating->page_rating, 'count'=>$rating->age_rating_count); if($rating->page_oldid==null) $rating=calculateRating($oldid); return formatRating($rating); } #------------------------------------------------------------------------------- # Given the rating array and the page oldid, generate HTML code to be # # displayed # #------------------------------------------------------------------------------- function getRatingHTML($rating, $oldid) { global $wgTitle, $wgScriptPath, $countLimit; $html=''; #generate stars for($x=0;$x<=4;$x++) { $html.='<a href="'. $wgTitle->getFullURL('oldid='.$oldid.'&rate='.($x+1)).'" rel="nofollow">'. '<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(); } } ?>