make Special:Random retry (once, but more carefully) if the chosen random offset was too high, provide error message if there really are no pages to choose from rather than going to the main page. rewrite Special:Randomredirect to reuse code from Special:Random.
This commit is contained in:
parent
8bd0a93609
commit
a5d5a6b5b8
7 changed files with 129 additions and 75 deletions
|
|
@ -323,6 +323,9 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
|
|||
* (bug 6910) Correct date/time formats in Vietnamese (vi)
|
||||
* (bug 9608) Correctly use ORDER BY in dumpLinks.php
|
||||
* (bug 9609) Correctly use ORDER BY in SpecialWhatlinkshere.php
|
||||
* Special:Random and Special:Randomredirect now try harder to send the user to
|
||||
a random page, and will give an error message if none really can be found
|
||||
instead of sending the user to the main page like they used to
|
||||
|
||||
== Maintenance ==
|
||||
|
||||
|
|
|
|||
|
|
@ -246,6 +246,7 @@ function __autoload($className) {
|
|||
'Language' => 'languages/Language.php',
|
||||
'PasswordResetForm' => 'includes/SpecialResetpass.php',
|
||||
'PatrolLog' => 'includes/PatrolLog.php',
|
||||
'RandomPage' => 'includes/SpecialRandompage.php',
|
||||
|
||||
// API classes
|
||||
'ApiBase' => 'includes/api/ApiBase.php',
|
||||
|
|
|
|||
|
|
@ -129,13 +129,14 @@ function wfSeedRandom() {
|
|||
* not likely to give duplicate values for any realistic
|
||||
* number of articles.
|
||||
*
|
||||
* @param float $limit Upper limit of returned values, default 1.
|
||||
* @return string
|
||||
*/
|
||||
function wfRandom() {
|
||||
function wfRandom( $limit = 1 ) {
|
||||
# The maximum random value is "only" 2^31-1, so get two random
|
||||
# values to reduce the chance of dupes
|
||||
$max = mt_getrandmax() + 1;
|
||||
$rand = number_format( (mt_rand() * $max + mt_rand())
|
||||
$rand = number_format( (mt_rand() * $max + mt_rand()) * $limit
|
||||
/ $max / $max, 12, '.', '' );
|
||||
return $rand;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,57 +1,122 @@
|
|||
<?php
|
||||
/**
|
||||
* @addtogroup SpecialPage
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Special page to direct the user to a random page
|
||||
*
|
||||
* @param $par The namespace to get a random page from (default NS_MAIN),
|
||||
* used as e.g. Special:Randompage/Category
|
||||
* @addtogroup SpecialPage
|
||||
* @author Rob Church <robchur@gmail.com>, Ilmari Karonen
|
||||
* @license GNU General Public Licence 2.0 or later
|
||||
*/
|
||||
function wfSpecialRandompage( $par = NS_MAIN ) {
|
||||
global $wgOut, $wgExtraRandompageSQL;
|
||||
$fname = 'wfSpecialRandompage';
|
||||
|
||||
# Determine namespace
|
||||
$t = Title::newFromText ( $par . ":Dummy" ) ;
|
||||
$namespace = $t->getNamespace () ;
|
||||
/**
|
||||
* Main execution point
|
||||
* @param $par Namespace to select the page from
|
||||
*/
|
||||
function wfSpecialRandompage( $par = null ) {
|
||||
global $wgOut, $wgContLang;
|
||||
|
||||
# NOTE! We use a literal constant in the SQL instead of the RAND()
|
||||
# function because RAND() will return a different value for every row
|
||||
# in the table. That's both very slow and returns results heavily
|
||||
# biased towards low values, as rows later in the table will likely
|
||||
# never be reached for comparison.
|
||||
#
|
||||
# Using a literal constant means the whole thing gets optimized on
|
||||
# the index, and the comparison is both fast and fair.
|
||||
$rnd = new RandomPage();
|
||||
$rnd->setNamespace( $wgContLang->getNsIndex( $par ) );
|
||||
$rnd->setRedirect( false );
|
||||
|
||||
# interpolation and sprintf() can muck up with locale-specific decimal separator
|
||||
$randstr = wfRandom();
|
||||
$title = $rnd->getRandomTitle();
|
||||
|
||||
$db = wfGetDB( DB_SLAVE );
|
||||
$use_index = $db->useIndexClause( 'page_random' );
|
||||
$page = $db->tableName( 'page' );
|
||||
|
||||
$extra = $wgExtraRandompageSQL ? "AND ($wgExtraRandompageSQL)" : '';
|
||||
$sql = "SELECT page_id,page_title
|
||||
FROM $page $use_index
|
||||
WHERE page_namespace=$namespace AND page_is_redirect=0 $extra
|
||||
AND page_random>$randstr
|
||||
ORDER BY page_random";
|
||||
$sql = $db->limitResult($sql, 1, 0);
|
||||
$res = $db->query( $sql, $fname );
|
||||
|
||||
$title = null;
|
||||
if( $s = $db->fetchObject( $res ) ) {
|
||||
$title =& Title::makeTitle( $namespace, $s->page_title );
|
||||
}
|
||||
if( is_null( $title ) ) {
|
||||
# That's not supposed to happen :)
|
||||
$title = Title::newMainPage();
|
||||
$wgOut->addWikiText( wfMsg( 'randompage-nopages' ) );
|
||||
return;
|
||||
}
|
||||
$wgOut->reportTime(); # for logfile
|
||||
|
||||
$wgOut->reportTime();
|
||||
$wgOut->redirect( $title->getFullUrl() );
|
||||
}
|
||||
|
||||
|
||||
class RandomPage {
|
||||
private $namespace = NS_MAIN; // namespace to select pages from
|
||||
private $redirect = false; // select redirects instead of normal pages?
|
||||
|
||||
public function getNamespace ( ) {
|
||||
return $this->namespace;
|
||||
}
|
||||
public function setNamespace ( $ns ) {
|
||||
if( $ns < NS_MAIN ) $ns = NS_MAIN;
|
||||
$this->namespace = $ns;
|
||||
}
|
||||
public function getRedirect ( ) {
|
||||
return $this->redirect;
|
||||
}
|
||||
public function setRedirect ( $redirect ) {
|
||||
$this->redirect = $redirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose a random title.
|
||||
* @return Title object (or null if nothing to choose from)
|
||||
*/
|
||||
public function getRandomTitle ( ) {
|
||||
$randstr = wfRandom();
|
||||
$row = $this->selectRandomPageFromDB( $randstr );
|
||||
|
||||
if( !$row ) {
|
||||
// Try again with a normalized value
|
||||
$randstr = wfRandom( $this->getMaxPageRandom() );
|
||||
$row = $this->selectRandomPageFromDB( $randstr );
|
||||
}
|
||||
|
||||
if( $row )
|
||||
return Title::makeTitleSafe( $this->namespace, $row->page_title );
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
private function selectRandomPageFromDB ( $randstr ) {
|
||||
global $wgExtraRandompageSQL;
|
||||
$fname = 'RandomPage::selectRandomPageFromDB';
|
||||
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
|
||||
$from = $this->getSQLFrom( $dbr );
|
||||
$where = $this->getSQLWhere( $dbr );
|
||||
|
||||
$sql = "SELECT page_title FROM $from
|
||||
WHERE $where AND page_random > $randstr
|
||||
ORDER BY page_random";
|
||||
|
||||
$sql = $dbr->limitResult( $sql, 1, 0 );
|
||||
$res = $dbr->query( $sql, $fname );
|
||||
return $dbr->fetchObject( $res );
|
||||
}
|
||||
|
||||
private function getMaxPageRandom () {
|
||||
$fname = 'RandomPage::getMaxPageRandom';
|
||||
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
|
||||
$from = $this->getSQLFrom( $dbr );
|
||||
$where = $this->getSQLWhere( $dbr );
|
||||
|
||||
$sql = "SELECT MAX(page_random) AS max FROM $from WHERE $where";
|
||||
|
||||
$sql = $dbr->limitResult( $sql, 1, 0 );
|
||||
$res = $dbr->query( $sql, $fname );
|
||||
$row = $dbr->fetchObject( $res );
|
||||
|
||||
return $row ? $row->max : 0;
|
||||
}
|
||||
|
||||
private function getSQLFrom ( $dbr ) {
|
||||
$use_index = $dbr->useIndexClause( 'page_random' );
|
||||
$page = $dbr->tableName( 'page' );
|
||||
return "$page $use_index";
|
||||
}
|
||||
|
||||
private function getSQLWhere ( $dbr ) {
|
||||
global $wgExtraRandompageSQL;
|
||||
$ns = (int) $this->namespace;
|
||||
$redirect = $this->redirect ? 1 : 0;
|
||||
$extra = $wgExtraRandompageSQL ? " AND ($wgExtraRandompageSQL)" : "";
|
||||
return "page_namespace = $ns AND page_is_redirect = $redirect" . $extra;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Special page to direct the user to a random redirect page (minus the second redirect)
|
||||
*
|
||||
* @addtogroup SpecialPage
|
||||
* @author Rob Church <robchur@gmail.com>
|
||||
* @author Rob Church <robchur@gmail.com>, Ilmari Karonen
|
||||
* @license GNU General Public Licence 2.0 or later
|
||||
*/
|
||||
|
||||
|
|
@ -12,40 +12,20 @@
|
|||
* Main execution point
|
||||
* @param $par Namespace to select the redirect from
|
||||
*/
|
||||
function wfSpecialRandomredirect( $par = NULL ) {
|
||||
global $wgOut, $wgExtraRandompageSQL, $wgContLang;
|
||||
$fname = 'wfSpecialRandomredirect';
|
||||
function wfSpecialRandomredirect( $par = null ) {
|
||||
global $wgOut, $wgContLang;
|
||||
|
||||
# Validate the namespace
|
||||
$namespace = $wgContLang->getNsIndex( $par );
|
||||
if( $namespace === false || $namespace < NS_MAIN )
|
||||
$namespace = NS_MAIN;
|
||||
$rnd = new RandomPage();
|
||||
$rnd->setNamespace( $wgContLang->getNsIndex( $par ) );
|
||||
$rnd->setRedirect( true );
|
||||
|
||||
# Same logic as RandomPage
|
||||
$randstr = wfRandom();
|
||||
$title = $rnd->getRandomTitle();
|
||||
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$use_index = $dbr->useIndexClause( 'page_random' );
|
||||
$page = $dbr->tableName( 'page' );
|
||||
if( is_null( $title ) ) {
|
||||
$wgOut->addWikiText( wfMsg( 'randomredirect-nopages' ) );
|
||||
return;
|
||||
}
|
||||
|
||||
$extra = $wgExtraRandompageSQL ? "AND ($wgExtraRandompageSQL)" : '';
|
||||
$sql = "SELECT page_id,page_title
|
||||
FROM $page $use_index
|
||||
WHERE page_namespace = $namespace AND page_is_redirect = 1 $extra
|
||||
AND page_random > $randstr
|
||||
ORDER BY page_random";
|
||||
|
||||
$sql = $dbr->limitResult( $sql, 1, 0 );
|
||||
$res = $dbr->query( $sql, $fname );
|
||||
|
||||
$title = NULL;
|
||||
if( $row = $dbr->fetchObject( $res ) )
|
||||
$title = Title::makeTitleSafe( $namespace, $row->page_title );
|
||||
|
||||
# Catch dud titles and return to the main page
|
||||
if( is_null( $title ) )
|
||||
$title = Title::newMainPage();
|
||||
|
||||
$wgOut->reportTime();
|
||||
$wgOut->redirect( $title->getFullUrl( 'redirect=no' ) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1475,6 +1475,7 @@ this old version, (rev) = revert to this old version.
|
|||
|
||||
# Random redirect
|
||||
'randomredirect' => 'Random redirect',
|
||||
'randomredirect-nopages' => 'There are no redirects in this namespace.',
|
||||
|
||||
# Statistics
|
||||
#
|
||||
|
|
@ -1560,6 +1561,7 @@ The [http://meta.wikimedia.org/wiki/Help:Job_queue job queue] length is '''$7'''
|
|||
'prefixindex' => 'Prefix index',
|
||||
'prefixindex-summary' => '',
|
||||
'randompage' => 'Random page',
|
||||
'randompage-nopages' => 'There are no pages in this namespace.',
|
||||
'randompage-url'=> 'Special:Random',
|
||||
'shortpages' => 'Short pages',
|
||||
'shortpages-summary' => '',
|
||||
|
|
|
|||
|
|
@ -991,6 +991,7 @@ Huomaa, että {{GRAMMAR:inessive|{{SITENAME}}}} muut voivat muokata tai poistaa
|
|||
|
||||
# Random redirect
|
||||
'randomredirect' => 'Satunnainen uudelleenohjaus',
|
||||
'randomredirect-nopages' => 'Tässä nimiavaruudessa ei ole uudelleenohjauksia.',
|
||||
|
||||
# Statistics
|
||||
'statistics' => 'Tilastot',
|
||||
|
|
@ -1049,6 +1050,7 @@ Ohjelmiston suorittamia ylläpitotöitä on jonossa '''$7''' {{PLURAL:$7|kappale
|
|||
'allpages' => 'Kaikki sivut',
|
||||
'prefixindex' => 'Sivut otsikon alun mukaan',
|
||||
'randompage' => 'Satunnainen sivu',
|
||||
'randompage-nopages' => 'Tässä nimiavaruudessa ei ole sivuja.',
|
||||
'shortpages' => 'Lyhyet sivut',
|
||||
'longpages' => 'Pitkät sivut',
|
||||
'deadendpages' => 'Sivut, joilla ei ole linkkejä',
|
||||
|
|
|
|||
Loading…
Reference in a new issue