RatingExtension/Source Code Dev
From PeacockWiki
(Difference between revisions)
| Revision as of 11:17, 31 July 2006 (edit) Trevorp (Talk | contribs) ← Previous diff |
Revision as of 11:23, 31 July 2006 (edit) Trevorp (Talk | contribs) Next diff → |
||
| Line 128: | Line 128: | ||
| } | } | ||
| - | function getPageList($namespace=array()) | + | function getPageList($namespace=array(), $limit=0) |
| { | { | ||
| $namespacestring=''; | $namespacestring=''; | ||
| Line 148: | Line 148: | ||
| } | } | ||
| - | function getRatingList($namespace=array()) | + | function getRatingList($namespace=array(), $limit=0) |
| { | { | ||
| global $wgNamespaceNamesEn; | global $wgNamespaceNamesEn; | ||
| Line 240: | Line 240: | ||
| $displayRating=(isset($parameters['displayrating'])?$parameters['displayrating'][0]:'true')!='false'; | $displayRating=(isset($parameters['displayrating'])?$parameters['displayrating'][0]:'true')!='false'; | ||
| $pattern=isset($parameters['pattern'])?$parameters['pattern'][0]:'[[$1|$2]]'.($displayRating?' ($3)':'').($displayCount?' ($4 ratings)':''); | $pattern=isset($parameters['pattern'])?$parameters['pattern'][0]:'[[$1|$2]]'.($displayRating?' ($3)':'').($displayCount?' ($4 ratings)':''); | ||
| + | $limit=isset($parameters['limit'])?$parameters['limit'][0]:-1; | ||
| foreach($ratings as $rating) | foreach($ratings as $rating) | ||
| { | { | ||
| + | if($limit--==0) break; | ||
| $output.=str_replace(array('$1', '$2', '$3', '$4'), array($rating['article'], strtr($rating['article'], '_', ' '), number_format($rating['rating'], 2), $rating['count']), $pattern)."\n\n"; | $output.=str_replace(array('$1', '$2', '$3', '$4'), array($rating['article'], strtr($rating['article'], '_', ' '), number_format($rating['rating'], 2), $rating['count']), $pattern)."\n\n"; | ||
| } | } | ||
Revision as of 11:23, 31 July 2006
<?php
$countLimit=3;
$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
#----------------
$sql = "REPLACE INTO `ratings` (`page_oldid`, `user_id`, `page_rating`) ".
"VALUES (".intval($_GET['oldid']).", '".
($wgUser->getID()?$wgUser->getID():$wgUser->getName()).
"', ".intval($_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=array(), $limit=0)
{
$namespacestring='';
$filterByNamespace=false;
foreach($namespace as $space)
{
if(is_numeric($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.')':"").';';
return runQuery2($sql);
}
function getRatingList($namespace=array(), $limit=0)
{
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 splitParameters($input)
{
$parameters=array();
foreach(split("\n", $input) as $parameter)
{
$parameter=split('=', $parameter, 2);
if(count($parameter)==2)
{
if(isset($parameters[$parameter[0]]))
$parameters[$parameter[0]][]=$parameter[1];
else
$parameters[$parameter[0]]=array($parameter[1]);
}
}
return $parameters;
}
function sortRatingsList($ratings, $sort)
{
$column='rating';
$order=-1;
foreach($sort as $item)
{
switch($item)
{
case 'rating':
$column='rating';
break;
case 'name':
$column='article';
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 'article':
$order=SORT_ASC;
break;
case 'count':
$order=SORT_DESC;
break;
default:
$order=SORT_DESC;
}
}
$val=array();
foreach($ratings as $rating)
{
$val[]=$rating[$column];
}
array_multisort($val, $order, $ratings);
return $ratings;
}
function renderRatings($input, $argv, &$parser)
{
$parameters=splitParameters($input);
$ratings=getRatingList(isset($parameters['namespace'])?$parameters['namespace']:array());
$ratings=sortRatingsList($ratings, isset($parameters['sortby'])?$parameters['sortby']:array());
$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]:-1;
foreach($ratings as $rating)
{
if($limit--==0) break;
$output.=str_replace(array('$1', '$2', '$3', '$4'), array($rating['article'], strtr($rating['article'], '_', ' '), number_format($rating['rating'], 2), $rating['count']), $pattern)."\n\n";
}
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(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 `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;
$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;
#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;
$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();
}
}
?>
