mirror of
https://bitbucket.org/vertlach/iusethis.git
synced 2024-06-17 07:30:50 +03:00
33f5015197
* CSS and JS are now separate RL modules * JS rewritten to use jQuery instead of sajax * Fixed a scoping bug from the previous patchset * Fixed other scoping bugs so that you can revoke your vote w/o reloading the page, no matter what * JS module is not loaded for users w/o the 'voteny' user right * JS is not loaded on Special:TopRatings anymore, it was only loaded there ever back when this extension had inline JS to prevent over 9000 JS errors, plus it wouldn't have worked because wgArticleId is 0 for special pages * Special page alias file added Change-Id: I6668238a0ab6272b0a7b3b167832ebb2d3abe2c2
199 lines
6.2 KiB
PHP
199 lines
6.2 KiB
PHP
<?php
|
|
/**
|
|
* A special page to display the highest rated pages on the wiki.
|
|
*
|
|
* This special page supports filtering by category and namespace, so
|
|
* {{Special:TopRatings/Adventure Games/0/10}} will show 10 ratings where the
|
|
* pages are in the "Adventure Games" category and the pages are in the main
|
|
* (0) namespace.
|
|
*
|
|
* @file
|
|
* @ingroup Extensions
|
|
* @date 11 December 2011
|
|
* @license To the extent that it is possible, this code is in the public domain
|
|
*/
|
|
class SpecialTopRatings extends IncludableSpecialPage {
|
|
|
|
/**
|
|
* Constructor -- set up the new special page
|
|
*/
|
|
public function __construct() {
|
|
parent::__construct( 'TopRatings' );
|
|
}
|
|
|
|
/**
|
|
* Show the special page
|
|
*
|
|
* @param mixed|null $par Parameter passed to the special page or null
|
|
*/
|
|
public function execute( $par ) {
|
|
// Set the page title, robot policies, etc.
|
|
$this->setHeaders();
|
|
|
|
$out = $this->getOutput();
|
|
$user = $this->getUser();
|
|
|
|
$categoryName = $namespace = '';
|
|
|
|
// Parse the parameters passed to the special page
|
|
// Make sure that the limit parameter passed to the special page is
|
|
// an integer and that it's less than 100 (performance!)
|
|
if ( isset( $par ) && is_numeric( $par ) && $par < 100 ) {
|
|
$limit = intval( $par );
|
|
} elseif ( isset( $par ) && !is_numeric( $par ) ) {
|
|
// $par is a string...assume that we can explode() it
|
|
$exploded = explode( '/', $par );
|
|
$categoryName = $exploded[0];
|
|
$namespace = ( isset( $exploded[1] ) ? intval( $exploded[1] ) : $namespace );
|
|
$limit = ( isset( $exploded[2] ) ? intval( $exploded[2] ) : 50 );
|
|
} else {
|
|
$limit = 50;
|
|
}
|
|
|
|
// Add CSS
|
|
$out->addModuleStyles( 'ext.voteNY.styles' );
|
|
/* scroll down some lines to see why I'm not including JS here anymore
|
|
if ( $user->isAllowed( 'voteny' ) ) {
|
|
$out->addModules( 'ext.voteNY.scripts' );
|
|
}
|
|
*/
|
|
|
|
$ratings = array();
|
|
$output = '';
|
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
|
$tables = $where = $joinConds = array();
|
|
$whatToSelect = array( 'DISTINCT vote_page_id' );
|
|
|
|
// By default we have no category and no namespace
|
|
$tables = array( 'Vote' );
|
|
$where = array( 'vote_page_id <> 0' );
|
|
|
|
// isset(), because 0 is a totally valid NS
|
|
if ( !empty( $categoryName ) && isset( $namespace ) ) {
|
|
$tables = array( 'Vote', 'page', 'categorylinks' );
|
|
$where = array(
|
|
'vote_page_id <> 0',
|
|
'cl_to' => str_replace( ' ', '_', $categoryName ),
|
|
'page_namespace' => $namespace
|
|
);
|
|
$joinConds = array(
|
|
'categorylinks' => array( 'INNER JOIN', 'cl_from = page_id' ),
|
|
'page' => array( 'INNER JOIN', 'page_id = vote_page_id' )
|
|
);
|
|
}
|
|
|
|
// Perform the SQL query with the given conditions; the basic idea is
|
|
// that we get $limit (however, 100 or less) unique page IDs from the
|
|
// Vote table. If a category and a namespace have been given, we also
|
|
// do an INNER JOIN with page and categorylinks table to get the
|
|
// correct data.
|
|
$res = $dbr->select(
|
|
$tables,
|
|
$whatToSelect,
|
|
$where,
|
|
__METHOD__,
|
|
array( 'LIMIT' => intval( $limit ) ),
|
|
$joinConds
|
|
);
|
|
|
|
foreach ( $res as $row ) {
|
|
// Add the results to the $ratings array and get the amount of
|
|
// votes the given page ID has
|
|
// For example: $ratings[1] = 11 = page with the page ID 1 has 11
|
|
// votes
|
|
$ratings[$row->vote_page_id] = (int)$dbr->selectField(
|
|
'Vote',
|
|
'SUM(vote_value)',
|
|
array( 'vote_page_id' => $row->vote_page_id ),
|
|
__METHOD__
|
|
);
|
|
}
|
|
|
|
// If we have some ratings, start building HTML output
|
|
if ( !empty( $ratings ) ) {
|
|
/* XXX dirrrrrrty hack! because when we include this page, the JS
|
|
* is not included, but we want things to work still
|
|
* Actually, this is way harder than what it looks like.
|
|
* The JS uses wgArticleId but when directly viewing Special:TopRatings,
|
|
* wgArticleId is zero, because special pages aren't articles.
|
|
* As for including the special page, then wgArticleId would likely
|
|
* point at the ID of the page that includes {{Special:TopRatings}},
|
|
* which would be stupid and wrong.
|
|
* Besides, shouldn't you check out the images/pages that you're gonna
|
|
* vote for? Yeah, that's what I thought, too.
|
|
if ( $this->including() && $user->isAllowed( 'voteny' ) ) {
|
|
global $wgExtensionAssetsPath;
|
|
$output .= '<script type="text/javascript" src="' .
|
|
$wgExtensionAssetsPath . '/VoteNY/Vote.js"></script>';
|
|
}
|
|
*/
|
|
|
|
// yes, array_keys() is needed
|
|
foreach ( array_keys( $ratings ) as $discardThis => $pageId ) {
|
|
$titleObj = Title::newFromId( $pageId );
|
|
if ( !( $titleObj instanceof Title ) ) {
|
|
continue;
|
|
}
|
|
|
|
$vote = new VoteStars( $pageId );
|
|
$output .= '<div class="user-list-rating">' .
|
|
Linker::link(
|
|
$titleObj,
|
|
$titleObj->getPrefixedText() // prefixed, so that the namespace shows!
|
|
) . $this->msg( 'word-separator' )->escaped() . // i18n overkill? ya betcha...
|
|
$this->msg( 'parentheses', $ratings[$pageId] )->escaped() .
|
|
'</div>';
|
|
|
|
$id = mt_rand(); // AFAIK these IDs are and originally were totally random...
|
|
$output .= "<div id=\"rating_stars_{$id}\">" .
|
|
$vote->displayStars(
|
|
$id,
|
|
self::getAverageRatingForPage( $pageId ),
|
|
false
|
|
) . '</div>';
|
|
$output .= "<div id=\"rating_{$id}\" class=\"rating-total\">" .
|
|
$vote->displayScore() .
|
|
'</div>';
|
|
}
|
|
} else {
|
|
// Nothing? Well, display an informative error message rather than
|
|
// a blank page or somesuch.
|
|
$output .= $this->msg( 'topratings-no-pages' )->escaped();
|
|
}
|
|
|
|
// Output everything!
|
|
$out->addHTML( $output );
|
|
}
|
|
|
|
/**
|
|
* Static version of Vote::getAverageVote().
|
|
*
|
|
* @param $pageId Integer: ID of the page for which we want to get the avg.
|
|
* rating
|
|
* @return Integer: average vote for the given page (ID)
|
|
*/
|
|
public static function getAverageRatingForPage( $pageId ) {
|
|
global $wgMemc;
|
|
|
|
$key = wfMemcKey( 'vote', 'avg', $pageId );
|
|
$data = $wgMemc->get( $key );
|
|
$voteAvg = 0;
|
|
|
|
if ( $data ) {
|
|
wfDebug( "Loading vote avg for page {$pageId} from cache (TopRatings)\n" );
|
|
$voteAvg = $data;
|
|
} else {
|
|
$dbr = wfGetDB( DB_SLAVE );
|
|
$voteAvg = (int)$dbr->selectField(
|
|
'Vote',
|
|
'AVG(vote_value) AS VoteAvg',
|
|
array( 'vote_page_id' => $pageId ),
|
|
__METHOD__
|
|
);
|
|
$wgMemc->set( $key, $voteAvg );
|
|
}
|
|
|
|
return $voteAvg;
|
|
}
|
|
} |