Improvements in MediaWiki namespace handling, enhanced rollback
This commit is contained in:
parent
ed14647e9d
commit
036ff960ce
6 changed files with 51 additions and 111 deletions
|
|
@ -402,7 +402,7 @@ class Article {
|
||||||
$this->showArticle( $text, wfMsg( "newarticle" ) );
|
$this->showArticle( $text, wfMsg( "newarticle" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateArticle( $text, $summary, $minor, $watchthis, $section = "")
|
function updateArticle( $text, $summary, $minor, $watchthis, $section = "", $forceBot = false )
|
||||||
{
|
{
|
||||||
global $wgOut, $wgUser, $wgLinkCache;
|
global $wgOut, $wgUser, $wgLinkCache;
|
||||||
global $wgDBtransactions, $wgMwRedir;
|
global $wgDBtransactions, $wgMwRedir;
|
||||||
|
|
@ -478,13 +478,14 @@ class Article {
|
||||||
$res = wfQuery( $sql, DB_WRITE, $fname );
|
$res = wfQuery( $sql, DB_WRITE, $fname );
|
||||||
$oldid = wfInsertID( $res );
|
$oldid = wfInsertID( $res );
|
||||||
|
|
||||||
|
$bot = (int)($wgUser->isBot() || $forceBot);
|
||||||
|
|
||||||
$sql = "INSERT INTO recentchanges (rc_timestamp,rc_cur_time," .
|
$sql = "INSERT INTO recentchanges (rc_timestamp,rc_cur_time," .
|
||||||
"rc_namespace,rc_title,rc_new,rc_minor,rc_bot,rc_cur_id,rc_user," .
|
"rc_namespace,rc_title,rc_new,rc_minor,rc_bot,rc_cur_id,rc_user," .
|
||||||
"rc_user_text,rc_comment,rc_this_oldid,rc_last_oldid) VALUES (" .
|
"rc_user_text,rc_comment,rc_this_oldid,rc_last_oldid) VALUES (" .
|
||||||
"'{$now}','{$now}'," . $this->mTitle->getNamespace() . ",'" .
|
"'{$now}','{$now}'," . $this->mTitle->getNamespace() . ",'" .
|
||||||
wfStrencode( $this->mTitle->getDBkey() ) . "',0,{$me2}," .
|
wfStrencode( $this->mTitle->getDBkey() ) . "',0,{$me2}," .
|
||||||
( $wgUser->isBot() ? 1 : 0 ) . "," .
|
"$bot," . $this->getID() . "," . $wgUser->getID() . ",'" .
|
||||||
$this->getID() . "," . $wgUser->getID() . ",'" .
|
|
||||||
wfStrencode( $wgUser->getName() ) . "','" .
|
wfStrencode( $wgUser->getName() ) . "','" .
|
||||||
wfStrencode( $summary ) . "',0,{$oldid})";
|
wfStrencode( $summary ) . "',0,{$oldid})";
|
||||||
wfQuery( $sql, DB_WRITE, $fname );
|
wfQuery( $sql, DB_WRITE, $fname );
|
||||||
|
|
@ -705,7 +706,7 @@ class Article {
|
||||||
|
|
||||||
function delete()
|
function delete()
|
||||||
{
|
{
|
||||||
global $wgUser, $wgOut;
|
global $wgUser, $wgOut, $wgMessageCache;
|
||||||
global $wpConfirm, $wpReason, $image, $oldimage;
|
global $wpConfirm, $wpReason, $image, $oldimage;
|
||||||
|
|
||||||
# This code desperately needs to be totally rewritten
|
# This code desperately needs to be totally rewritten
|
||||||
|
|
@ -719,6 +720,12 @@ class Article {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Can't delete cached MediaWiki namespace (i.e. vital messages)
|
||||||
|
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI && $wgMessageCache->isCacheable( $this->mTitle->getDBkey() ) ) {
|
||||||
|
$wgOut->fatalError( wfMsg( "cannotdelete" ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
# Better double-check that it hasn't been deleted yet!
|
# Better double-check that it hasn't been deleted yet!
|
||||||
$wgOut->setPagetitle( wfMsg( "confirmdelete" ) );
|
$wgOut->setPagetitle( wfMsg( "confirmdelete" ) );
|
||||||
if ( ( "" == trim( $this->mTitle->getText() ) )
|
if ( ( "" == trim( $this->mTitle->getText() ) )
|
||||||
|
|
@ -973,7 +980,10 @@ class Article {
|
||||||
$wgOut->readOnlyPage( $this->getContent() );
|
$wgOut->readOnlyPage( $this->getContent() );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Secret enhanced rollback, marks edits rc_bot=1
|
||||||
|
$bot = !!$_REQUEST['bot'];
|
||||||
|
|
||||||
# Replace all this user's current edits with the next one down
|
# Replace all this user's current edits with the next one down
|
||||||
$tt = wfStrencode( $this->mTitle->getDBKey() );
|
$tt = wfStrencode( $this->mTitle->getDBKey() );
|
||||||
$n = $this->mTitle->getNamespace();
|
$n = $this->mTitle->getNamespace();
|
||||||
|
|
@ -1007,7 +1017,7 @@ class Article {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the last edit not by this guy
|
# Get the last edit not by this guy
|
||||||
$sql = "SELECT old_text,old_user,old_user_text
|
$sql = "SELECT old_text,old_user,old_user_text,old_timestamp
|
||||||
FROM old USE INDEX (name_title_timestamp)
|
FROM old USE INDEX (name_title_timestamp)
|
||||||
WHERE old_namespace={$n} AND old_title='{$tt}'
|
WHERE old_namespace={$n} AND old_title='{$tt}'
|
||||||
AND (old_user <> {$uid} OR old_user_text <> '{$ut}')
|
AND (old_user <> {$uid} OR old_user_text <> '{$ut}')
|
||||||
|
|
@ -1020,19 +1030,27 @@ class Article {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$s = wfFetchObject( $res );
|
$s = wfFetchObject( $res );
|
||||||
|
|
||||||
|
if ( $bot ) {
|
||||||
|
# Mark all reverted edits as bot
|
||||||
|
$sql = "UPDATE recentchanges SET rc_bot=1 WHERE
|
||||||
|
rc_cur_id=$pid AND rc_user=$uid AND rc_timestamp > '{$s->old_timestamp}'";
|
||||||
|
wfQuery( $sql, DB_WRITE, $fname );
|
||||||
|
}
|
||||||
|
|
||||||
# Save it!
|
# Save it!
|
||||||
$newcomment = wfMsg( "revertpage", $s->old_user_text );
|
$newcomment = wfMsg( "revertpage", $s->old_user_text );
|
||||||
$wgOut->setPagetitle( wfMsg( "actioncomplete" ) );
|
$wgOut->setPagetitle( wfMsg( "actioncomplete" ) );
|
||||||
$wgOut->setRobotpolicy( "noindex,nofollow" );
|
$wgOut->setRobotpolicy( "noindex,nofollow" );
|
||||||
$wgOut->addHTML( "<h2>" . $newcomment . "</h2>\n<hr>\n" );
|
$wgOut->addHTML( "<h2>" . $newcomment . "</h2>\n<hr>\n" );
|
||||||
$this->updateArticle( $s->old_text, $newcomment, 1, $this->mTitle->userIsWatching() );
|
$this->updateArticle( $s->old_text, $newcomment, 1, $this->mTitle->userIsWatching(), "", $bot );
|
||||||
|
|
||||||
global $wgEnablePersistentLC;
|
global $wgEnablePersistentLC;
|
||||||
if ( $wgEnablePersistentLC ) {
|
if ( $wgEnablePersistentLC ) {
|
||||||
wfQuery("DELETE FROM linkscc WHERE lcc_pageid='{$pid}'", DB_WRITE);
|
wfQuery("DELETE FROM linkscc WHERE lcc_pageid='{$pid}'", DB_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$wgOut->returnToMain( false );
|
$wgOut->returnToMain( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1061,6 +1079,7 @@ class Article {
|
||||||
/* private */ function editUpdates( $text )
|
/* private */ function editUpdates( $text )
|
||||||
{
|
{
|
||||||
global $wgDeferredUpdateList, $wgDBname, $wgMemc;
|
global $wgDeferredUpdateList, $wgDBname, $wgMemc;
|
||||||
|
global $wgMessageCache;
|
||||||
|
|
||||||
wfSeedRandom();
|
wfSeedRandom();
|
||||||
if ( 0 == mt_rand( 0, 999 ) ) {
|
if ( 0 == mt_rand( 0, 999 ) ) {
|
||||||
|
|
@ -1070,6 +1089,8 @@ class Article {
|
||||||
}
|
}
|
||||||
$id = $this->getID();
|
$id = $this->getID();
|
||||||
$title = $this->mTitle->getPrefixedDBkey();
|
$title = $this->mTitle->getPrefixedDBkey();
|
||||||
|
$shortTitle = $this->mTitle->getDBkey();
|
||||||
|
|
||||||
$adj = $this->mCountAdjustment;
|
$adj = $this->mCountAdjustment;
|
||||||
|
|
||||||
if ( 0 != $id ) {
|
if ( 0 != $id ) {
|
||||||
|
|
@ -1080,24 +1101,11 @@ class Article {
|
||||||
$u = new SearchUpdate( $id, $title, $text );
|
$u = new SearchUpdate( $id, $title, $text );
|
||||||
array_push( $wgDeferredUpdateList, $u );
|
array_push( $wgDeferredUpdateList, $u );
|
||||||
|
|
||||||
$u = new UserTalkUpdate( 1, $this->mTitle->getNamespace(),
|
$u = new UserTalkUpdate( 1, $this->mTitle->getNamespace(), $shortTitle );
|
||||||
$this->mTitle->getDBkey() );
|
|
||||||
array_push( $wgDeferredUpdateList, $u );
|
array_push( $wgDeferredUpdateList, $u );
|
||||||
|
|
||||||
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
|
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
|
||||||
$messageCache = $wgMemc->get( "$wgDBname:messages" );
|
$wgMessageCache->replace( $shortTitle, $text );
|
||||||
|
|
||||||
# If another thread is loading, poll
|
|
||||||
for ( $i=0; $i<70 && $messageCache == 'loading'; $i++ ) {
|
|
||||||
sleep(1);
|
|
||||||
$messageCache = $wgMemc->get( "$wgDBname:messages" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !$messageCache || $messageCache == 'loading' ) {
|
|
||||||
$messageCache = wfLoadAllMessages();
|
|
||||||
}
|
|
||||||
$messageCache[$this->mTitle->getDBkey()] = $text;
|
|
||||||
$wgMemc->set( "$wgDBname:messages", $messageCache, 86400 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ $wgShowIPinHeader = true; # For non-logged in users
|
||||||
# Translation using MediaWiki: namespace
|
# Translation using MediaWiki: namespace
|
||||||
# Not recommended unless memcached is installed
|
# Not recommended unless memcached is installed
|
||||||
$wgUseDatabaseMessages = false;
|
$wgUseDatabaseMessages = false;
|
||||||
|
$wgMsgCacheExpiry = 86400;
|
||||||
|
|
||||||
$wgExtraSubtitle = "";
|
$wgExtraSubtitle = "";
|
||||||
$wgSiteSupportPage = "";
|
$wgSiteSupportPage = "";
|
||||||
|
|
|
||||||
|
|
@ -213,85 +213,24 @@ function wfMsgNoDB( $key ) {
|
||||||
|
|
||||||
# Really get a message
|
# Really get a message
|
||||||
function wfMsgReal( $key, $args, $useDB ) {
|
function wfMsgReal( $key, $args, $useDB ) {
|
||||||
global $wgLang, $wgReplacementKeys, $wgMemc, $wgDBname;
|
global $wgReplacementKeys, $wgMessageCache, $wgLang;
|
||||||
global $wgUseDatabaseMessages, $wgUseMemCached, $wgOut;
|
|
||||||
global $wgAllMessagesEn, $wgLanguageCode;
|
|
||||||
|
|
||||||
$fname = "wfMsg";
|
$fname = "wfMsg";
|
||||||
wfProfileIn( $fname );
|
wfProfileIn( $fname );
|
||||||
|
if ( $wgMessageCache ) {
|
||||||
static $messageCache = false;
|
$message = $wgMessageCache->get( $key, $useDB );
|
||||||
$memcKey = "$wgDBname:messages";
|
} elseif ( $wgLang ) {
|
||||||
$fname = "wfMsg";
|
|
||||||
$message = false;
|
|
||||||
|
|
||||||
# newFromText is too slow!
|
|
||||||
$title = ucfirst( $key );
|
|
||||||
if ( $messageCache ) {
|
|
||||||
$message = $messageCache[$title];
|
|
||||||
} elseif ( !$wgUseDatabaseMessages || !$useDB ) {
|
|
||||||
$message = $wgLang->getMessage( $key );
|
$message = $wgLang->getMessage( $key );
|
||||||
|
} else {
|
||||||
|
wfDebug( "No language object when getting $key\n" );
|
||||||
|
$message = "<$key>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !$message && $wgUseMemCached ) {
|
|
||||||
# Try memcached
|
|
||||||
if ( !$messageCache ) {
|
|
||||||
$messageCache = $wgMemc->get( $memcKey );
|
|
||||||
}
|
|
||||||
|
|
||||||
# If there's nothing in memcached, load all the messages from the database
|
|
||||||
# This should only happen on server reset -- ordinary changes should update
|
|
||||||
# memcached in editUpdates()
|
|
||||||
if ( !$messageCache ) {
|
|
||||||
# Other threads don't need to load the messages if another thread is doing it.
|
|
||||||
$wgMemc->set( $memcKey, "loading", time() + 60 );
|
|
||||||
$messageCache = wfLoadAllMessages();
|
|
||||||
# Save in memcached
|
|
||||||
$wgMemc->set( $memcKey, $messageCache, time() + 3600 );
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
if ( is_array( $messageCache ) && array_key_exists( $title, $messageCache ) ) {
|
|
||||||
$message = $messageCache[$title];
|
|
||||||
} elseif ( $messageCache == "loading" ) {
|
|
||||||
$messageCache = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# If there was no MemCached, load each message from the DB individually
|
|
||||||
if ( !$message ) {
|
|
||||||
if ( $useDB ) {
|
|
||||||
$sql = "SELECT cur_text FROM cur WHERE cur_namespace=" . NS_MEDIAWIKI .
|
|
||||||
" AND cur_title='$title'";
|
|
||||||
$res = wfQuery( $sql, DB_READ, $fname );
|
|
||||||
|
|
||||||
if ( wfNumRows( $res ) ) {
|
|
||||||
$obj = wfFetchObject( $res );
|
|
||||||
$message = $obj->cur_text;
|
|
||||||
wfFreeResult( $res );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Try the array in $wgLang
|
|
||||||
if ( !$message ) {
|
|
||||||
$message = $wgLang->getMessage( $key );
|
|
||||||
}
|
|
||||||
|
|
||||||
# Try the English array
|
|
||||||
if ( !$message && $wgLanguageCode != "en" ) {
|
|
||||||
$message = Language::getMessage( $key );
|
|
||||||
}
|
|
||||||
|
|
||||||
# Replace arguments
|
# Replace arguments
|
||||||
if( count( $args ) ) {
|
if( count( $args ) ) {
|
||||||
$message = str_replace( $wgReplacementKeys, $args, $message );
|
$message = str_replace( $wgReplacementKeys, $args, $message );
|
||||||
}
|
}
|
||||||
wfProfileOut( $fname );
|
wfProfileOut( $fname );
|
||||||
if ( !$message ) {
|
|
||||||
# Failed, message does not exist
|
|
||||||
return "<$key>";
|
|
||||||
}
|
|
||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -702,20 +641,6 @@ function wfEscapeWikiText( $text )
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Loads the entire MediaWiki namespace, returns the array
|
|
||||||
function wfLoadAllMessages()
|
|
||||||
{
|
|
||||||
$sql = "SELECT cur_title,cur_text FROM cur WHERE cur_namespace=" . NS_MEDIAWIKI;
|
|
||||||
$res = wfQuery( $sql, DB_READ, $fname );
|
|
||||||
|
|
||||||
$messages = array();
|
|
||||||
for ( $row = wfFetchObject( $res ); $row; $row = wfFetchObject( $res ) ) {
|
|
||||||
$messages[$row->cur_title] = $row->cur_text;
|
|
||||||
}
|
|
||||||
wfFreeResult( $res );
|
|
||||||
return $messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
function wfQuotedPrintable( $string, $charset = "" )
|
function wfQuotedPrintable( $string, $charset = "" )
|
||||||
{
|
{
|
||||||
# Probably incomplete; see RFC 2045
|
# Probably incomplete; see RFC 2045
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,9 @@ class Namespace {
|
||||||
|
|
||||||
function isMovable( $index )
|
function isMovable( $index )
|
||||||
{
|
{
|
||||||
if ( $index < NS_MAIN || $index > NS_WP_TALK ) { return false; }
|
if ( $index < NS_MAIN || $index == NS_IMAGE ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ wfProfileIn( $fname );
|
||||||
global $wgUseDynamicDates;
|
global $wgUseDynamicDates;
|
||||||
wfProfileIn( "$fname-includes" );
|
wfProfileIn( "$fname-includes" );
|
||||||
|
|
||||||
# Only files which are used on every invocation should be included here
|
|
||||||
# Otherwise, include them conditionally [TS]
|
|
||||||
include_once( "GlobalFunctions.php" );
|
include_once( "GlobalFunctions.php" );
|
||||||
include_once( "Namespace.php" );
|
include_once( "Namespace.php" );
|
||||||
include_once( "Skin.php" );
|
include_once( "Skin.php" );
|
||||||
|
|
@ -37,12 +35,15 @@ include_once( "MemCachedClient.inc.php" );
|
||||||
include_once( "Block.php" );
|
include_once( "Block.php" );
|
||||||
include_once( "SearchEngine.php" );
|
include_once( "SearchEngine.php" );
|
||||||
include_once( "DifferenceEngine.php" );
|
include_once( "DifferenceEngine.php" );
|
||||||
|
include_once( "MessageCache.php" );
|
||||||
|
|
||||||
wfProfileOut( "$fname-includes" );
|
wfProfileOut( "$fname-includes" );
|
||||||
wfProfileIn( "$fname-memcached" );
|
wfProfileIn( "$fname-memcached" );
|
||||||
global $wgUser, $wgLang, $wgOut, $wgTitle;
|
global $wgUser, $wgLang, $wgOut, $wgTitle;
|
||||||
global $wgArticle, $wgDeferredUpdateList, $wgLinkCache;
|
global $wgArticle, $wgDeferredUpdateList, $wgLinkCache;
|
||||||
global $wgMemc, $wgMagicWords, $wgMwRedir, $wgDebugLogFile;
|
global $wgMemc, $wgMagicWords, $wgMwRedir, $wgDebugLogFile;
|
||||||
|
global $wgMessageCache, $wgUseMemCached, $wgUseDatabaseMessages;
|
||||||
|
global $wgMsgCacheExpiry, $wgDBname;
|
||||||
|
|
||||||
class MemCachedClientforWiki extends MemCachedClient {
|
class MemCachedClientforWiki extends MemCachedClient {
|
||||||
function _debug( $text ) {
|
function _debug( $text ) {
|
||||||
|
|
@ -68,6 +69,8 @@ wfProfileIn( "$fname-misc" );
|
||||||
|
|
||||||
include_once( "Language.php" );
|
include_once( "Language.php" );
|
||||||
|
|
||||||
|
$wgMessageCache = new MessageCache( $wgUseMemCached, $wgUseDatabaseMessages, $wgMsgCacheExpiry, $wgDBname );
|
||||||
|
|
||||||
$wgOut = new OutputPage();
|
$wgOut = new OutputPage();
|
||||||
wfDebug( "\n\n" );
|
wfDebug( "\n\n" );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ class MovePageForm {
|
||||||
{
|
{
|
||||||
global $wgOut, $wgUser, $wgLang;
|
global $wgOut, $wgUser, $wgLang;
|
||||||
global $wpNewTitle, $wpOldTitle, $wpMovetalk, $target;
|
global $wpNewTitle, $wpOldTitle, $wpMovetalk, $target;
|
||||||
global $wgDeferredUpdateList;
|
global $wgDeferredUpdateList, $wgMessageCache;
|
||||||
$fname = "MovePageForm::doSubmit";
|
$fname = "MovePageForm::doSubmit";
|
||||||
|
|
||||||
$this->ot = Title::newFromText( $wpOldTitle );
|
$this->ot = Title::newFromText( $wpOldTitle );
|
||||||
|
|
@ -134,7 +134,8 @@ class MovePageForm {
|
||||||
( ! Namespace::isMovable( $nns ) ) ||
|
( ! Namespace::isMovable( $nns ) ) ||
|
||||||
( "" == $this->ndt ) ||
|
( "" == $this->ndt ) ||
|
||||||
( "" != $this->nt->getInterwiki() ) ||
|
( "" != $this->nt->getInterwiki() ) ||
|
||||||
( !$this->nt->userCanEdit() ) ) {
|
( !$this->nt->userCanEdit() ) ||
|
||||||
|
( $this->ons == NS_MEDIAWIKI && $wgMessageCache->isCacheable( $this->odt ) ) ) {
|
||||||
$this->showForm( wfMsg( "badarticleerror" ) );
|
$this->showForm( wfMsg( "badarticleerror" ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue