RatingExtension/Source Code Dev

From PeacockWiki

(Difference between revisions)
Jump to: navigation, search
Revision as of 04:02, 31 July 2006 (edit)
137.166.81.96 (Talk)

← Previous diff
Revision as of 06:29, 31 July 2006 (edit)
137.166.81.96 (Talk)

Next diff →
Line 1: Line 1:
<pre><?php <pre><?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
 +);
################################################################################ ################################################################################
Line 40: Line 61:
#---------------- #----------------
$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 ); $dbr =& wfGetDB( DB_WRITE );
$res=wfQuery($sql, DB_WRITE, ""); $res=wfQuery($sql, DB_WRITE, "");
Line 107: Line 128:
} }
-function getPageList($namespace=false)+function getPageList($namespace=array())
{ {
 + $namespacestring='';
$sql="SELECT `page_title` AS `title`, `page_namespace` AS `namespace`, $sql="SELECT `page_title` AS `title`, `page_namespace` AS `namespace`,
`page_latest` AS `oldid` FROM `page`". `page_latest` AS `oldid` FROM `page`".
- ($namespace===false?"":'WHERE `page_namespace` IN ('.$namespace.')').';';+ (count($namespace)>0?"":'WHERE `page_namespace` IN ('.$namespacestring.')').';';
return runQuery2($sql); return runQuery2($sql);
} }
Line 128: Line 150:
} }
return $ratings; return $ratings;
 +}
 +
 +function splitParameters($input)
 +{
 + $parameters=array();
 + foreach(split("\n", $input) as $parameter)
 + {
 + $parameter=split('=', $parameter);
 + if(count($parameter)==2)
 + {
 + if(isset($parameters[$parameter[0]]))
 + $parameters[$parameter[0]][]=$parameter[1];
 + else
 + $parameters[$parameter[0]]=array($parameter[1]);
 + }
 + }
 + var_dump($parameters);
} }
function renderRatings($input, $argv, &$parser) function renderRatings($input, $argv, &$parser)
{ {
- $ratings=getRatingList('0,1,2,3');+ $parameters=splitParameters($input);
 + $ratings=getRatingList();
$output=''; $output='';
foreach($ratings as $rating) foreach($ratings as $rating)
Line 145: Line 185:
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
function InsertRating($parserOutput, $text) { function InsertRating($parserOutput, $text) {
-//TODO: Limit by namespace+ global $wgArticle, $allowedNamespaces;
- 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()]) if(!$allowedNamespaces[$wgArticle->getTitle()->getNamespace()])
return; return;
Line 227: Line 246:
return $oldid; return $oldid;
$dbr =& wfGetDB( DB_SLAVE ); $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` ". $sql="SELECT `page_latest` AS `oldid` FROM `page` ".
"WHERE `page_id`=".$article->getID().";"; "WHERE `page_id`=".$article->getID().";";
Line 273: Line 290:
function getRating($oldid) function getRating($oldid)
{ {
- global $wgTitle;+ global $wgTitle, $countLimit;
- +
- $countlimit=3;+
$ratingdata=getRatingData($oldid); $ratingdata=getRatingData($oldid);
Line 282: Line 297:
$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($rating->count<$countLimit)
{ {
$count=$ratingdata->count; $count=$ratingdata->count;
Line 291: Line 306:
$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 298: Line 313:
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 326: Line 341:
function getRatingHTML($rating, $oldid) function getRatingHTML($rating, $oldid)
{ {
- global $wgTitle, $wgScriptPath;+ global $wgTitle, $wgScriptPath, $countLimit;
- $countlimit=3;+
$html=''; $html='';
#generate stars #generate stars
Line 336: Line 350:
'<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 349: Line 363:
#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;
} }

Revision as of 06:29, 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())
{
  $namespacestring='';
  $sql="SELECT `page_title` AS `title`, `page_namespace` AS `namespace`, 
    `page_latest` AS `oldid` FROM `page`".
    (count($namespace)>0?"":'WHERE `page_namespace` IN ('.$namespacestring.')').';';
  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 splitParameters($input)
{
  $parameters=array();
  foreach(split("\n", $input) as $parameter)
  {
    $parameter=split('=', $parameter);
    if(count($parameter)==2)
    {
      if(isset($parameters[$parameter[0]]))
        $parameters[$parameter[0]][]=$parameter[1];
      else
        $parameters[$parameter[0]]=array($parameter[1]);
    }
  }
  var_dump($parameters);
}

function renderRatings($input, $argv, &$parser)
{
  $parameters=splitParameters($input);
  $ratings=getRatingList();
  $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) {
  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);
#  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;
  $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();
  }
}

?>
Personal tools