From 3c969496827a4ea71d87e4f535a664b15d68b84f Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Sat, 17 Jan 2004 05:49:39 +0000 Subject: [PATCH] * Recent Changes improvements: object oriented back end, move page annotation and (untested) message queue feed. * Misc. bugs fixed in DatabaseFunctions.php and Skin.php. * install-utils, install and update utilise Database objects instead of handling their own connections * schema change for RC improvement -- added rc_type, rc_moved_to_title and rc_moved_to_ns --- includes/Article.php | 79 ++-- includes/Database.php | 104 ++++- includes/DatabaseFunctions.php | 67 ++-- includes/DefaultSettings.php | 1 + includes/DifferenceEngine.php | 35 +- includes/LogPage.php | 10 +- includes/RecentChange.php | 263 +++++++++++++ includes/Setup.php | 1 + includes/Skin.php | 512 +++++++++++++++---------- includes/SpecialMovepage.php | 35 +- includes/SpecialRecentchanges.php | 29 +- includes/SpecialUserlogin.php | 5 +- includes/Title.php | 15 + install-utils.inc | 11 +- install.php | 34 +- maintenance/archives/patch-rc_type.sql | 6 + maintenance/tables.sql | 5 +- update.php | 65 ++-- wiki.phtml | 9 +- 19 files changed, 874 insertions(+), 412 deletions(-) create mode 100644 includes/RecentChange.php create mode 100644 maintenance/archives/patch-rc_type.sql diff --git a/includes/Article.php b/includes/Article.php index 522616dde3..807007f1c7 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -20,16 +20,17 @@ class Article { /* private */ var $mCounter, $mComment, $mCountAdjustment; /* private */ var $mMinorEdit, $mRedirectedFrom; /* private */ var $mTouched, $mFileCache, $mTitle; - + /* private */ var $mId, $mTable; + function Article( &$title ) { $this->mTitle =& $title; $this->clear(); } - + /* private */ function clear() { $this->mContentLoaded = false; - $this->mUser = $this->mCounter = -1; # Not loaded + $this->mCurID = $this->mUser = $this->mCounter = -1; # Not loaded $this->mRedirectedFrom = $this->mUserText = $this->mTimestamp = $this->mComment = $this->mFileCache = ""; $this->mCountAdjustment = 0; @@ -67,6 +68,7 @@ class Article { # Note that getContent/loadContent may follow redirects if # not told otherwise, and so may cause a change to mTitle. + # Return the text of this revision function getContent( $noredir = false ) { global $action,$section,$count; # From query string @@ -117,7 +119,8 @@ class Article { } } } - + + # Load the revision (including cur_text) into this object function loadContent( $noredir = false ) { global $wgOut, $wgMwRedir; @@ -125,21 +128,8 @@ class Article { if ( $this->mContentLoaded ) return; $fname = "Article::loadContent"; - - # Pre-fill content with error message so that if something - # fails we'll have something telling us what we intended. - - $t = $this->mTitle->getPrefixedText(); - if ( isset( $oldid ) ) { - $oldid = IntVal( $oldid ); - $t .= ",oldid={$oldid}"; - } - if ( isset( $redirect ) ) { - $redirect = ($redirect == "no") ? "no" : "yes"; - $t .= ",redirect={$redirect}"; - } - $this->mContent = wfMsg( "missingarticle", $t ); - + $success = true; + if ( ! $oldid ) { # Retrieve current version $id = $this->getID(); if ( 0 == $id ) return; @@ -212,6 +202,22 @@ class Article { $this->mTimestamp = $s->old_timestamp; wfFreeResult( $res ); } + + # Return error message :P + # Horrible, confusing UI and data. I think this should return false on error -- TS + if ( !$success ) { + $t = $this->mTitle->getPrefixedText(); + if ( isset( $oldid ) ) { + $oldid = IntVal( $oldid ); + $t .= ",oldid={$oldid}"; + } + if ( isset( $redirect ) ) { + $redirect = ($redirect == "no") ? "no" : "yes"; + $t .= ",redirect={$redirect}"; + } + $this->mContent = wfMsg( "missingarticle", $t ); + } + $this->mContentLoaded = true; } @@ -246,7 +252,7 @@ class Article { return 1; } - # Load the field related to the last edit time of the article. + # Loads everything from cur except cur_text # This isn't necessary for all uses, so it's only done if needed. /* private */ function loadLastEdit() @@ -399,16 +405,8 @@ class Article { $this->mTitle->resetArticleID( $newid ); Article::onArticleCreate( $this->mTitle ); + RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary ); - $sql = "INSERT INTO recentchanges (rc_timestamp,rc_cur_time," . - "rc_namespace,rc_title,rc_new,rc_minor,rc_cur_id,rc_user," . - "rc_user_text,rc_comment,rc_this_oldid,rc_last_oldid,rc_bot) VALUES (" . - "'{$now}','{$now}',{$ns},'" . wfStrencode( $ttl ) . "',1," . - ( $isminor ? 1 : 0 ) . ",{$newid}," . $wgUser->getID() . ",'" . - wfStrencode( $wgUser->getName() ) . "','" . - wfStrencode( $summary ) . "',0,0," . - ( $wgUser->isBot() ? 1 : 0 ) . ")"; - wfQuery( $sql, DB_WRITE, $fname ); if ($watchthis) { if(!$this->mTitle->userIsWatching()) $this->watch(); } else { @@ -505,27 +503,8 @@ class Article { $oldid = wfInsertID( $res ); $bot = (int)($wgUser->isBot() || $forceBot); - - $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_user_text,rc_comment,rc_this_oldid,rc_last_oldid) VALUES (" . - "'{$now}','{$now}'," . $this->mTitle->getNamespace() . ",'" . - wfStrencode( $this->mTitle->getDBkey() ) . "',0,{$me2}," . - "$bot," . $this->getID() . "," . $wgUser->getID() . ",'" . - wfStrencode( $wgUser->getName() ) . "','" . - wfStrencode( $summary ) . "',0,{$oldid})"; - wfQuery( $sql, DB_WRITE, $fname ); - - $sql = "UPDATE recentchanges SET rc_this_oldid={$oldid} " . - "WHERE rc_namespace=" . $this->mTitle->getNamespace() . " AND " . - "rc_title='" . wfStrencode( $this->mTitle->getDBkey() ) . "' AND " . - "rc_timestamp='" . $this->getTimestamp() . "'"; - wfQuery( $sql, DB_WRITE, $fname ); - - $sql = "UPDATE recentchanges SET rc_cur_time='{$now}' " . - "WHERE rc_cur_id=" . $this->getID(); - wfQuery( $sql, DB_WRITE, $fname ); - + RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $this->getComment(), + $oldid, $this->getTimestamp() ); Article::onArticleEdit( $this->mTitle ); } diff --git a/includes/Database.php b/includes/Database.php index c243b5dd17..8e6282e345 100644 --- a/includes/Database.php +++ b/includes/Database.php @@ -6,6 +6,9 @@ define( "DB_READ", -1 ); define( "DB_WRITE", -2 ); define( "DB_LAST", -3 ); +define( "LIST_COMMA", 0 ); +define( "LIST_AND", 1 ); + class Database { #------------------------------------------------------------------------------ @@ -16,7 +19,7 @@ class Database { /* private */ var $mIgnoreErrors = false; /* private */ var $mServer, $mUser, $mPassword, $mConn, $mDBname; - /* private */ var $mOut, $mDebug; + /* private */ var $mOut, $mDebug, $mOpened = false; /* private */ var $mFailFunction; @@ -51,7 +54,8 @@ class Database { # Get functions function lastQuery() { return $this->mLastQuery; } - + function isOpen() { return $this->mOpened; } + #------------------------------------------------------------------------------ # Other functions #------------------------------------------------------------------------------ @@ -84,12 +88,12 @@ class Database { $this->mServer = $server; $this->mUser = $user; $this->mPassword = $password; - $this->mDbName = $dbName; + $this->mDBname = $dbName; $success = false; @$this->mConn = mysql_connect( $server, $user, $password ); - if ( $this->mConn !== false ) { + if ( $this->mConn !== false && $dbName != "" ) { $success = @mysql_select_db( $dbName, $this->mConn ); if ( !$success ) { wfDebug( "Error selecting database \"$dbName\": " . $this->lastError() . "\n" ); @@ -105,6 +109,7 @@ class Database { $this->reportConnectionError(); $this->close(); } + $this->mOpened = $success; return $success; } @@ -112,6 +117,7 @@ class Database { # Returns success, true if already closed function close() { + $this->mOpened = false; if ( $this->mConn ) { return mysql_close( $this->mConn ); } else { @@ -132,7 +138,7 @@ class Database { # Usually aborts on failure # If errors are explicitly ignored, returns success - function query( $sql, $db, $fname = "" ) + function query( $sql, $fname = "" ) { global $wgProfiling; @@ -211,6 +217,23 @@ class Database { return $ret; } + # More complex SELECT wrapper, single row only + # Aborts or returns FALSE on error + # Takes an array of selected variables, and a condition map, which is ANDed + # e.g. getArray( "cur", array( "cur_id" ), array( "cur_namespace" => 0, "cur_title" => "Astronomy" ) ) + # would return an object where $obj->cur_id is the ID of the Astronomy article + function getArray( $table, $vars, $conds, $fname = "Database::getArray" ) + { + $vars = implode( ",", $vars ); + $where = Database::makeList( $conds, LIST_AND ); + $sql = "SELECT $vars FROM $table WHERE $where"; + $res = $this->query( $sql, $fname ); + if ( $res === false || !$this->numRows( $res ) ) { + return false; + } + return $this->fetchObject( $res ); + } + # Removes most variables from an SQL query and replaces them with X or N for numbers. # It's only slightly flawed. Don't use for anything important. /* static */ function generalizeSQL( $sql ) @@ -277,6 +300,32 @@ class Database { return $found; } + function tableExists( $table ) + { + $res = mysql_list_tables( $this->mDBname ); + if( !$res ) { + echo "** " . $this->lastError() . "\n"; + return false; + } + for( $i = $this->numRows( $res ) - 1; $i--; $i > 0 ) { + if( mysql_tablename( $res, $i ) == $table ) return true; + } + return false; + } + + function fieldInfo( $table, $field ) + { + $res = $this->query( "SELECT * FROM $table LIMIT 1" ); + $n = mysql_num_fields( $res ); + for( $i = 0; $i < $n; $i++ ) { + $meta = mysql_fetch_field( $res, $i ); + if( $field == $meta->name ) { + return $meta; + } + } + return false; + } + # INSERT wrapper, inserts an array into a table # Keys are field names, values are values # Usually aborts on failure @@ -284,23 +333,52 @@ class Database { function insertArray( $table, $a, $fname = "Database::insertArray" ) { $sql1 = "INSERT INTO $table ("; - $sql2 = "VALUES ("; + $sql2 = "VALUES (" . Database::makeList( $a ); $first = true; foreach ( $a as $field => $value ) { - if ( $first ) { + if ( !$first ) { $sql1 .= ","; - $sql2 .= ","; - $first = false; } + $first = false; $sql1 .= $field; + } + $sql = "$sql1) $sql2)"; + return !!$this->query( $sql, $fname ); + } + + # Makes a wfStrencoded list from an array + # $mode: LIST_COMMA - comma separated + # LIST_AND - ANDed WHERE clause (without the WHERE) + /* static */ function makeList( $a, $mode = LIST_COMMA) + { + $first = true; + $list = ""; + foreach ( $a as $field => $value ) { + if ( !$first ) { + if ( $mode == LIST_AND ) { + $list .= " AND "; + } else { + $list .= ","; + } + } else { + $first = false; + } + if ( $mode == LIST_AND ) { + $list .= "$field="; + } if ( is_string( $value ) ) { - $sql2 .= "'" . wfStrencode( $value ) . "'"; + $list .= "'" . wfStrencode( $value ) . "'"; } else { - $sql2 .= $value; + $list .= $value; } } - $sql = "$sql1) $sql2)"; - return !!$this->query( $sql, DB_WRITE, $fname ); + return $list; + } + + function selectDB( $db ) + { + $this->mDatabase = $db; + mysql_select_db( $db, $this->mConn ); } } diff --git a/includes/DatabaseFunctions.php b/includes/DatabaseFunctions.php index b3208e168b..0add9fd536 100644 --- a/includes/DatabaseFunctions.php +++ b/includes/DatabaseFunctions.php @@ -2,8 +2,16 @@ # Backwards compatibility wrapper for Database.php +# I imagine this file will eventually become a backwards +# compatibility wrapper around a load balancer object, and +# the load balancer will finally call Database, which will +# represent a single connection + # NB: This file follows a connect on demand scheme. Do -# not access the $wgDatabase variable directly, use wfGetDB() +# not access the $wgDatabase variable directly unless +# you intend to set it. Use wfGetDB(). + +include_once( "Database.php" ); # Query the database # $db: DB_READ = -1 read from slave (or only server) @@ -12,9 +20,6 @@ # Replication is not actually implemented just yet # Usually aborts on failure # If errors are explicitly ignored, returns success - -include_once( "Database.php" ); - function wfQuery( $sql, $db, $fname = "" ) { global $wgDatabase, $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, @@ -25,12 +30,12 @@ function wfQuery( $sql, $db, $fname = "" ) $wgOut->fatalError( wfMsgNoDB( "wrong_wfQuery_params", $db, $sql ) ); } - $db = wfGetDB(); - return $db->query( $sql, $db, $fname ); + $db =& wfGetDB(); + return $db->query( $sql, $fname ); } # Connect on demand -function wfGetDB() +function &wfGetDB() { global $wgDatabase, $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDebugDumpSql, $wgBufferSQLResults, $wgIgnoreSQLErrors; @@ -47,7 +52,7 @@ function wfGetDB() function wfBufferSQLResults( $newstate ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->setBufferResults( $newstate ); } @@ -60,97 +65,109 @@ function wfBufferSQLResults( $newstate ) function wfIgnoreSQLErrors( $newstate ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->setIgnoreErrors( $newstate ); } function wfFreeResult( $res ) { - $db = wfGetDB(); + $db =& wfGetDB(); $db->freeResult( $res ); } function wfFetchObject( $res ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->fetchObject( $res ); } function wfNumRows( $res ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->numRows( $res ); } function wfNumFields( $res ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->numFields( $res ); } function wfFieldName( $res, $n ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->fieldName( $res, $n ); } function wfInsertId() { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->insertId(); } function wfDataSeek( $res, $row ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->dataSeek( $res, $row ); } function wfLastErrno() { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->lastErrno(); } function wfLastError() { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->lastError(); } function wfAffectedRows() { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->affectedRows(); } function wfLastDBquery() { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->lastQuery(); } function wfSetSQL( $table, $var, $value, $cond ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->set( $table, $var, $value, $cond ); } function wfGetSQL( $table, $var, $cond ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->get( $table, $var, $cond ); } function wfFieldExists( $table, $field ) { - $db = wfGetDB(); + $db =& wfGetDB(); return $db->fieldExists( $table, $field ); } function wfIndexExists( $table, $index ) { - $db = wfGetDB(); - return $wgDatabase->indexExists( $table, $index ); + $db =& wfGetDB(); + return $db->indexExists( $table, $index ); +} + +function wfInsertArray( $table, $array ) +{ + $db =& wfGetDB(); + return $db->insertArray( $table, $array ); +} + +function wfGetArray( $table, $vars, $conds, $fname = "wfGetArray" ) +{ + $db =& wfGetDB(); + return $db->getArray( $table, $vars, $conds, $fname ); } ?> diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 7e40447546..f226f2ed40 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -64,6 +64,7 @@ $wgAmericanDates = false; # Enable for English module to print dates # as eg 'May 12' instead of '12 May' $wgLocalInterwiki = "w"; $wgShowIPinHeader = true; # For non-logged in users +$wgMaxNameChars = 32; # Maximum number of bytes in username # Translation using MediaWiki: namespace # Not recommended unless memcached is installed diff --git a/includes/DifferenceEngine.php b/includes/DifferenceEngine.php index 30af4a2cc5..c3188c79f7 100644 --- a/includes/DifferenceEngine.php +++ b/includes/DifferenceEngine.php @@ -5,7 +5,8 @@ class DifferenceEngine { /* private */ var $mOldid, $mNewid; /* private */ var $mOldtitle, $mNewtitle; /* private */ var $mOldtext, $mNewtext; - + /* private */ var $mOldUser, $mNewUser; + function DifferenceEngine( $old, $new ) { $this->mOldid = $old; @@ -29,9 +30,17 @@ class DifferenceEngine { $wgOut->supressQuickbar(); $wgOut->setSubtitle( wfMsg( "difference" ) ); $wgOut->setRobotpolicy( "noindex,follow" ); + + $sk = $wgUser->getSkin(); + $oldUserTitle = Title::makeTitle( NS_USER, $this->mOldUser ); + $newUserTitle = Title::makeTitle( NS_USER, $this->mNewUser ); + $oldUserLink = $sk->makeLinkObj( $oldUserTitle, $this->mOldUser ); + $newUserLink = $sk->makeLinkObj( $newUserTitle, $this->mNewUser ); + $oldHeader = "{$this->mOldtitle}
$oldUserLink"; + $newHeader = "{$this->mNewtitle}
$newUserLink"; DifferenceEngine::showDiff( $this->mOldtext, $this->mNewtext, - $this->mOldtitle, $this->mNewtitle ); + $oldHeader, $newHeader ); $wgOut->addHTML( "

{$this->mNewtitle}

\n" ); $wgOut->addWikiText( $this->mNewtext ); } @@ -48,9 +57,9 @@ class DifferenceEngine { $wgOut->addHTML( " +{$otitle} +{$ntitle}\n" ); $diffs = new Diff( $ota, $nta ); @@ -68,20 +77,21 @@ cellpadding=0 cellspacing='4px'> { global $wgTitle, $wgOut, $wgLang; $fname = "DifferenceEngine::loadText"; - + if ( 0 == $this->mNewid || 0 == $this->mOldid ) { $wgOut->setArticleFlag( true ); $this->mNewtitle = wfMsg( "currentrev" ); $id = $wgTitle->getArticleID(); - - $sql = "SELECT cur_text FROM cur WHERE cur_id={$id}"; + + $sql = "SELECT cur_text, cur_user_text FROM cur WHERE cur_id={$id}"; $res = wfQuery( $sql, DB_READ, $fname ); if ( 0 == wfNumRows( $res ) ) { return false; } $s = wfFetchObject( $res ); $this->mNewtext = $s->cur_text; + $this->mNewUser = $s->cur_user_text; } else { - $sql = "SELECT old_timestamp,old_text,old_flags FROM old WHERE " . + $sql = "SELECT old_timestamp,old_text,old_flags,old_user_text FROM old WHERE " . "old_id={$this->mNewid}"; $res = wfQuery( $sql, DB_READ, $fname ); @@ -92,15 +102,17 @@ cellpadding=0 cellspacing='4px'> $t = $wgLang->timeanddate( $s->old_timestamp, true ); $this->mNewtitle = wfMsg( "revisionasof", $t ); + $this->mNewUser = $s->old_user_text; } if ( 0 == $this->mOldid ) { - $sql = "SELECT old_timestamp,old_text,old_flags FROM old USE INDEX (name_title_timestamp) WHERE " . + $sql = "SELECT old_timestamp,old_text,old_flags,old_user_text " . + "FROM old USE INDEX (name_title_timestamp) WHERE " . "old_namespace=" . $wgTitle->getNamespace() . " AND " . "old_title='" . wfStrencode( $wgTitle->getDBkey() ) . "' ORDER BY inverse_timestamp LIMIT 1"; $res = wfQuery( $sql, DB_READ, $fname ); } else { - $sql = "SELECT old_timestamp,old_text,old_flags FROM old WHERE " . + $sql = "SELECT old_timestamp,old_text,old_flags,old_user_text FROM old WHERE " . "old_id={$this->mOldid}"; $res = wfQuery( $sql, DB_READ, $fname ); } @@ -111,7 +123,8 @@ cellpadding=0 cellspacing='4px'> $t = $wgLang->timeanddate( $s->old_timestamp, true ); $this->mOldtitle = wfMsg( "revisionasof", $t ); - + $this->mOldUser = $s->old_user_text; + return true; } } diff --git a/includes/LogPage.php b/includes/LogPage.php index 0faeab679e..371820e764 100644 --- a/includes/LogPage.php +++ b/includes/LogPage.php @@ -81,13 +81,9 @@ class LogPage { # And update recentchanges if ( $this->mUpdateRecentChanges ) { - $sql = "INSERT INTO recentchanges (rc_timestamp,rc_cur_time, - rc_user,rc_user_text,rc_namespace,rc_title,rc_comment, - rc_cur_id) VALUES ('{$now}','{$now}',{$uid},'{$ut}',4,'" . - wfStrencode( $this->mTitle ) . "','" . - wfStrencode( $this->mComment ) . "',{$this->mId})"; - wfQuery( $sql, DB_WRITE, $fname ); - } + $titleObj = Title::makeTitle( Namespace::getWikipedia(), $this->mTitle ); + RecentChange::notifyLog( $now, $titleObj, $wgUser, $this->mComment ); + } return true; } diff --git a/includes/RecentChange.php b/includes/RecentChange.php new file mode 100644 index 0000000000..d7e8a6d979 --- /dev/null +++ b/includes/RecentChange.php @@ -0,0 +1,263 @@ +loadFromRow( $row ); + return $rc; + } + + # Accessors + + function setAttribs( $attribs ) + { + $this->mAttribs = $attribs; + } + + function setExtra( $extra ) + { + $this->mExtra = $extra; + } + + function getTitle() + { + if ( $this->mTitle === false ) { + $this->mTitle = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] ); + } + return $this->mTitle; + } + + function getMovedToTitle() + { + if ( $this->mMovedToTitle === false ) { + $this->mMovedToTitle = Title::makeTitle( $this->mAttribs['rc_moved_to_ns'], + $this->mAttribs['rc_moved_to_title'] ); + } + return $this->mMovedToTitle; + } + + # Writes the data in this object to the database + function save() + { + global $wgUseRCQueue, $wgRCQueueID, $wgLocalInterwiki; + $fname = "RecentChange::save"; + + if ( !is_array($this->mExtra) ) { + $this->mExtra = array(); + } + $this->mExtra['lang'] = $wgLocalInterwiki; + + # Insert new row + wfInsertArray( "recentchanges", $this->mAttribs, $fname ); + + # Update old rows, if necessary + if ( $this->mAttribs['rc_type'] == RC_EDIT ) { + $oldid = $this->mAttribs['rc_last_oldid']; + $ns = $this->mAttribs['rc_namespace']; + $title = wfStrencode($this->mAttribs['rc_title']); + $lastTime = $this->mExtra['lastTimestamp']; + $now = $this->mAttribs['rc_timestamp']; + $curId = $this->mAttribs['rc_cur_id']; + + # Update rc_this_oldid for the entries which were current + $sql = "UPDATE recentchanges SET rc_this_oldid={$oldid} " . + "WHERE rc_namespace=$ns AND rc_title='$title' AND rc_timestamp='$lastTime'"; + wfQuery( $sql, DB_WRITE, $fname ); + + # Update rc_cur_time + $sql = "UPDATE recentchanges SET rc_cur_time='{$now}' " . + "WHERE rc_cur_id=" . $curId; + wfQuery( $sql, DB_WRITE, $fname ); + } + + # Notify external application + if ( $wgUseRCQueue ) { + $queue = msg_get_queue( $wgRCQueueID ); + if (!msg_send( $queue, array_merge( $this->mAttribs, 1, $this->mExtra ), + true, false, $error )) + { + wfDebug( "Error sending message to RC queue, code $error\n" ); + } + } + } + + # Makes an entry in the database corresponding to an edit + /*static*/ function notifyEdit( $timestamp, &$title, $minor, &$user, $comment, + $oldId, $lastTimestamp ) + { + $rc = new RecentChange; + $rc->mAttribs = array( + 'rc_timestamp' => $timestamp, + 'rc_cur_time' => $timestamp, + 'rc_namespace' => $title->getNamespace(), + 'rc_title' => $title->getDBkey(), + 'rc_type' => RC_EDIT, + 'rc_minor' => $minor ? 1 : 0, + 'rc_cur_id' => $title->getArticleID(), + 'rc_user' => $user->getID(), + 'rc_user_text' => $user->getName(), + 'rc_comment' => $comment, + 'rc_this_oldid' => 0, + 'rc_last_oldid' => $oldId, + 'rc_bot' => $user->isBot() ? 1 : 0, + 'rc_moved_to_ns' => 0, + 'rc_moved_to_title' => '' + ); + + $rc->mExtra = array( + 'prefixedDBkey' => $title->getPrefixedDBkey(), + 'lastTimestamp' => $lastTimestamp + ); + $rc->save(); + } + + # Makes an entry in the database corresponding to page creation + # Note: the title object must be loaded with the new id using resetArticleID() + /*static*/ function notifyNew( $timestamp, &$title, $minor, &$user, $comment ) + { + $rc = new RecentChange; + $rc->mAttribs = array( + 'rc_timestamp' => $timestamp, + 'rc_cur_time' => $timestamp, + 'rc_namespace' => $title->getNamespace(), + 'rc_title' => $title->getDBkey(), + 'rc_type' => RC_NEW, + 'rc_minor' => $minor ? 1 : 0, + 'rc_cur_id' => $title->getArticleID(), + 'rc_user' => $user->getID(), + 'rc_user_text' => $user->getName(), + 'rc_comment' => $comment, + 'rc_this_oldid' => 0, + 'rc_last_oldid' => 0, + 'rc_bot' => $user->isBot() ? 1 : 0, + 'rc_moved_to_ns' => 0, + 'rc_moved_to_title' => '' + ); + + $rc->mExtra = array( + 'prefixedDBkey' => $title->getPrefixedDBkey(), + 'lastTimestamp' => 0 + ); + $rc->save(); + } + + # Makes an entry in the database corresponding to a rename + /*static*/ function notifyMove( $timestamp, &$oldTitle, &$newTitle, &$user, $comment ) + { + $rc = new RecentChange; + $rc->mAttribs = array( + 'rc_timestamp' => $timestamp, + 'rc_cur_time' => $timestamp, + 'rc_namespace' => $oldTitle->getNamespace(), + 'rc_title' => $oldTitle->getDBkey(), + 'rc_type' => RC_MOVE, + 'rc_minor' => 0, + 'rc_cur_id' => $oldTitle->getArticleID(), + 'rc_user' => $user->getID(), + 'rc_user_text' => $user->getName(), + 'rc_comment' => $comment, + 'rc_this_oldid' => 0, + 'rc_last_oldid' => 0, + 'rc_bot' => $user->isBot() ? 1 : 0, + 'rc_moved_to_ns' => $newTitle->getNamespace(), + 'rc_moved_to_title' => $newTitle->getDBkey() + ); + + $rc->mExtra = array( + 'prefixedDBkey' => $oldTitle->getPrefixedDBkey(), + 'lastTimestamp' => 0, + 'prefixedMoveTo' => $newTitle->getPrefixedDBkey() + ); + $rc->save(); + } + + # A log entry is different to an edit in that previous revisions are + # not kept + /*static*/ function notifyLog( $timestamp, &$title, &$user, $comment ) + { + $rc = new RecentChange; + $rc->mAttribs = array( + 'rc_timestamp' => $timestamp, + 'rc_cur_time' => $timestamp, + 'rc_namespace' => $title->getNamespace(), + 'rc_title' => $title->getDBkey(), + 'rc_type' => RC_LOG, + 'rc_minor' => 0, + 'rc_cur_id' => $title->getArticleID(), + 'rc_user' => $user->getID(), + 'rc_user_text' => $user->getName(), + 'rc_comment' => $comment, + 'rc_this_oldid' => 0, + 'rc_last_oldid' => 0, + 'rc_bot' => 0, + 'rc_moved_to_ns' => 0, + 'rc_moved_to_title' => '' + ); + $rc->mExtra = array( + 'prefixedDBkey' => $title->getPrefixedDBkey(), + 'lastTimestamp' => 0 + ); + $rc->save(); + } + + # Initialises the members of this object from a mysql row object + function loadFromRow( $row ) + { + $this->mAttribs = get_object_vars( $row ); + $this->mExtra = array(); + } + + # Gets the end part of the diff URL assoicated with this object + # Blank if no diff link should be displayed + function diffLinkTrail( $forceCur ) + { + if ( $this->mAttribs['rc_type'] == RC_EDIT ) { + $trail = "curid=" . (int)($this->mAttribs['rc_cur_id']) . + "&oldid=" . (int)($this->mAttribs['rc_last_oldid']); + if ( $forceCur ) { + $trail .= "&diff=0" ; + } else { + $trail .= "&diff=" . (int)($this->mAttribs['rc_this_oldid']); + } + } else { + $trail = ""; + } + return $trail; + } +} +?> diff --git a/includes/Setup.php b/includes/Setup.php index dcb53781ca..29a60049c6 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -24,6 +24,7 @@ wfProfileIn( "$fname-includes" ); include_once( "GlobalFunctions.php" ); include_once( "Namespace.php" ); +include_once( "RecentChange.php" ); include_once( "Skin.php" ); include_once( "OutputPage.php" ); include_once( "User.php" ); diff --git a/includes/Skin.php b/includes/Skin.php index e0416f47e8..d15272e9d1 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -9,6 +9,8 @@ "Standard", "Nostalgia", "CologneBlue" #, "Smarty", "Montparnasse" ); +include_once( "RecentChange.php" ); + # For some odd PHP bug, this function can't be part of a class function getCategories () { @@ -26,20 +28,19 @@ function getCategories () return $s ; } - -class RecentChangesClass { - var $secureName , $displayName , $link , $namespace ; - var $oldid , $diffid , $timestamp , $curlink , $lastlink , $usertalklink , $versionlink ; - var $usercomment , $userlink ; - var $isminor , $isnew , $watched , $islog ; - } ; +class RCCacheEntry extends RecentChange +{ + var $secureName, $link; + var $curlink , $lastlink , $usertalklink , $versionlink ; + var $userlink, $timestamp, $watched; +} ; class Skin { /* private */ var $lastdate, $lastline; var $rc_cache ; # Cache for Enhanced Recent Changes - var $rccc ; # Recent Changes Cache Counter for visibility toggle + var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle function Skin() @@ -67,16 +68,16 @@ class Skin { return $q; } - function initPage() + function initPage( &$out ) { - global $wgOut, $wgStyleSheetPath; + global $wgStyleSheetPath; $fname = "Skin::initPage"; wfProfileIn( $fname ); - - $wgOut->addLink( "shortcut icon", "", "/favicon.ico" ); - if ( $wgOut->isPrintable() ) { $ss = "wikiprintable.css"; } + + $out->addLink( "shortcut icon", "", "/favicon.ico" ); + if ( $out->isPrintable() ) { $ss = "wikiprintable.css"; } else { $ss = $this->getStylesheet(); } - $wgOut->addLink( "stylesheet", "", "{$wgStyleSheetPath}/{$ss}" ); + $out->addLink( "stylesheet", "", "{$wgStyleSheetPath}/{$ss}" ); wfProfileOut( $fname ); } @@ -84,7 +85,7 @@ class Skin { global $wgDebugComments; wfProfileIn( "Skin::outputPage" ); - $this->initPage(); + $this->initPage( $out ); $out->out( $out->headElement() ); $out->out( "\nrc_cache = array() ; + $this->rcCacheIndex = 0 ; $this->lastdate = ""; return ""; } @@ -1664,6 +1666,8 @@ class Skin { return $s; } + # Returns text for the end of RC + # If enhanced RC is in use, returns pretty much all the text function endRecentChangesList() { $s = $this->recentChangesBlock() ; @@ -1671,77 +1675,101 @@ class Skin { return $s; } - function endImageHistoryList() + # Enhanced RC ungrouped line + function recentChangesBlockLine ( $rcObj ) { - $s = "\n"; - return $s; - } - - function recentChangesBlockLine ( $y ) { global $wgUploadPath ; - - $M = wfMsg( "minoreditletter" ); - $N = wfMsg( "newpageletter" ); + + # Get rc_xxxx variables + extract( $rcObj->mAttribs ) ; + $curIdEq = "curid=$rc_cur_id"; + + # Spacer image $r = "" ; - $r .= "" ; - $r .= "" ; - if ( $y->isnew ) $r .= $N ; - else $r .= " " ; - if ( $y->isminor ) $r .= $M ; - else $r .= " " ; - $r .= " ".$y->timestamp." " ; + $r .= "" ; $r .= "" ; + + if ( $rc_type == RC_MOVE ) { + $r .= "  "; + } else { + # M & N (minor & new) + $M = wfMsg( "minoreditletter" ); + $N = wfMsg( "newpageletter" ); + + if ( $rc_type == RC_NEW ) { + $r .= $N ; + } else { + $r .= " " ; + } + if ( $rc_minor ) { + $r .= $M ; + } else { + $r .= " " ; + } + } + + # Timestamp + $r .= " ".$rcObj->timestamp." " ; $r .= "" ; - $link = $y->link ; - if ( $y->watched ) $link = "{$link}" ; + + # Article link + $link = $rcObj->link ; + if ( $rcObj->watched ) $link = "{$link}" ; $r .= $link ; + # Cur $r .= " (" ; - $r .= $y->curlink ; + $r .= $rcObj->curlink ; $r .= "; " ; - $r .= $this->makeKnownLink( $y->secureName, wfMsg( "hist" ), "action=history" ); + + # Hist + $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( "hist" ), "{$curIdEq}&action=history" ); - $r .= ") . . ".$y->userlink ; - $r .= $y->usertalklink ; - if ( $y->usercomment != "" ) - $r .= " (".wfEscapeHTML($y->usercomment).")" ; + # User/talk + $r .= ") . . ".$rcObj->userlink ; + $r .= $rcObj->usertalklink ; + + # Comment + if ( $rc_comment != "" && $rc_type != RC_MOVE ) + $r .= " (".wfEscapeHTML($rc_comment).")" ; $r .= "
\n" ; return $r ; - } + } - function recentChangesBlockGroup ( $y ) { + # Enhanced RC group + function recentChangesBlockGroup ( $block ) + { global $wgUploadPath ; - + $r = "" ; $M = wfMsg( "minoreditletter" ); $N = wfMsg( "newpageletter" ); + + # Collate list of users $isnew = false ; $userlinks = array () ; - foreach ( $y AS $x ) { - $oldid = $x->diffid ; - if ( $x->isnew ) $isnew = true ; - $u = $x->userlink ; + foreach ( $block AS $rcObj ) { + $oldid = $rcObj->mAttribs['rc_last_oldid']; + if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ; + $u = $rcObj->userlink ; if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ; $userlinks[$u]++ ; - } - + } + + # Sort the list and convert to text krsort ( $userlinks ) ; asort ( $userlinks ) ; $users = array () ; - $u = array_keys ( $userlinks ) ; - foreach ( $u as $x ) { - $z = $x ; - if ( $userlinks[$x] > 1 ) $z .= " ({$userlinks[$x]}×)" ; - array_push ( $users , $z ) ; - } + foreach ( $userlinks as $userlink => $count) { + $text = $userlink ; + if ( $count > 1 ) $text .= " ({$count}×)" ; + array_push ( $users , $text ) ; + } $users = " [".implode("; ",$users)."]" ; - $e = $y ; - $e = array_shift ( $e ) ; - # Arrow - $rci = "RCI{$this->rccc}" ; - $rcl = "RCL{$this->rccc}" ; - $rcm = "RCM{$this->rccc}" ; + $rci = "RCI{$this->rcCacheIndex}" ; + $rcl = "RCL{$this->rcCacheIndex}" ; + $rcm = "RCM{$this->rcCacheIndex}" ; $tl = "" ; $tl .= "" ; $tl .= "" ; @@ -1749,246 +1777,318 @@ class Skin { $r .= $tl ; # Main line + # M/N $r .= "" ; if ( $isnew ) $r .= $N ; else $r .= " " ; $r .= " " ; # Minor - $r .= " ".$e->timestamp." " ; - $r .= "" ; - $link = $e->link ; - if ( $e->watched ) $link = "{$link}" ; + # Timestamp + $r .= " ".$block[0]->timestamp." " ; + $r .= "
" ; + + # Article link + $link = $block[0]->link ; + if ( $block[0]->watched ) $link = "{$link}" ; $r .= $link ; - - if ( !$e->islog ) { - $r .= " (".count($y)." " ; + + $curIdEq = "curid=" . $block[0]->mAttribs['rc_cur_id']; + if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) { + # Changes + $r .= " (".count($block)." " ; if ( $isnew ) $r .= wfMsg("changes"); - else $r .= $this->makeKnownLink( $e->secureName , wfMsg("changes") , "diff=0&oldid=".$oldid ) ; + else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg("changes") , + "{$curIdEq}&diff=0&oldid=".$oldid ) ; $r .= "; " ; - $r .= $this->makeKnownLink( $e->secureName, wfMsg( "history" ), "action=history" ); + + # History + $r .= $this->makeKnownLink( $block[0]->getTitle(), wfMsg( "history" ), "{$curIdEq}&action=history" ); $r .= ")" ; - } + } $r .= $users ; $r .= "
\n" ; # Sub-entries $r .= "\n" ; - $this->rccc++ ; + $this->rcCacheIndex++ ; return $r ; - } + } + # If enhanced RC is in use, this function takes the previously cached + # RC lines, arranges them, and outputs the HTML function recentChangesBlock () { global $wgUploadPath ; if ( count ( $this->rc_cache ) == 0 ) return "" ; - $k = array_keys ( $this->rc_cache ) ; - foreach ( $k AS $x ) - { - $y = $this->rc_cache[$x] ; - if ( count ( $y ) < 2 ) { - $r .= $this->recentChangesBlockLine ( array_shift ( $y ) ) ; + #$k = array_keys ( $this->rc_cache ) ; + foreach ( $this->rc_cache AS $secureName => $block ) { + if ( count ( $block ) < 2 ) { + $r .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ; } else { - $r .= $this->recentChangesBlockGroup ( $y ) ; - } + $r .= $this->recentChangesBlockGroup ( $block ) ; } + } return "
{$r}
" ; } - function recentChangesLine( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 ) + # Called in a loop over all displayed RC entries + # Either returns the line, or caches it for later use + function recentChangesLine( $row, $watched = false ) { global $wgUser ; $usenew = $wgUser->getOption( "usenewrc" ); if ( $usenew ) - $r = $this->recentChangesLineNew ( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched , $oldid , $diffid ) ; + $line = $this->recentChangesLineNew ( $row, $watched ) ; else - $r = $this->recentChangesLineOld ( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched , $oldid , $diffid ) ; - return $r ; + $line = $this->recentChangesLineOld ( $row, $watched ) ; + return $line ; } - - function recentChangesLineOld( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0, $diffid = 0 ) + + function recentChangesLineOld( $row, $watched = false ) { global $wgTitle, $wgLang, $wgUser; - - $d = $wgLang->date( $ts, true); + + # Extract DB fields into local scope + extract( get_object_vars( $row ) ); + $rc = RecentChange::newFromRow( $row ); + $curIdEq = "curid=" . $rc_cur_id; + + # Make date header if necessary + $date = $wgLang->date( $rc_timestamp, true); $s = ""; - if ( $d != $this->lastdate ) { + if ( $date != $this->lastdate ) { if ( "" != $this->lastdate ) { $s .= "\n"; } - $s .= "

{$d}

\n
    "; - $this->lastdate = $d; + $s .= "

    {$date}

    \n
      "; + $this->lastdate = $date; } - $h = $wgLang->time( $ts, true ); - $t = Title::makeName( $ns, $ttl ); - $clink = $this->makeKnownLink( $t , "" ); - $nt = Title::newFromText( $t ); - - if ( $watched ) { - $clink = "{$clink}"; - } - $hlink = $this->makeKnownLink( $t, wfMsg( "hist" ), "action=history" ); - if ( $isnew || $nt->isLog() ) { - $dlink = wfMsg( "diff" ); + $s .= "
    • "; + + if ( $rc_type == RC_MOVE ) { + # Diff + $s .= "(" . wfMsg( "diff" ) . ") ("; + # Hist + $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( "hist" ), "action=history" ) . + ") . . "; + + # "[[x]] moved to [[y]]" + $s .= $this->makeKnownLinkObj( $rc->getTitle(), "", "redirect=no" ); + $s .= " " . wfMsg( "movedto" ). " "; + $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), "" ); } else { - $dlink = $this->makeKnownLink( $t, wfMsg( "diff" ), - "diff={$oldid}&oldid={$diffid}" ); # Finagle's law + # Diff link + if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) { + $diffLink = wfMsg( "diff" ); + } else { + $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "diff" ), + "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}" ); + } + $s .= "($diffLink) ("; + + # History link + $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "hist" ), "{$curIdEq}&action=history" ); + $s .= ") . . "; + + # M and N (minor and new) + $M = wfMsg( "minoreditletter" ); + $N = wfMsg( "newpageletter" ); + if ( $rc_minor ) { $s .= " {$M}"; } + if ( $rc_type == RC_NEW ) { $s .= "{$N}"; } + + # Article link + $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), "" ); + + if ( $watched ) { + $articleLink = "{$articleLink}"; + } + $s .= " $articleLink"; + } - if ( 0 == $u ) { - $ul = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ), - $ut, "target=" . $ut ); + + # Timestamp + $s .= "; " . $wgLang->time( $rc_timestamp, true ) . " . . "; + + # User link (or contributions for unregistered users) + if ( 0 == $rc_user ) { + $userLink = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ), + $rc_user_text, "target=" . $rc_user_text ); } else { - $ul = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) . ":{$ut}", $ut ); + $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ":{$rc_user_text}", $rc_user_text ); } - - $talkname=$wgLang->getNsText(Namespace::getTalk(0)); # use the shorter name + $s .= $userLink; + + # User talk link + $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name global $wgDisableAnonTalk; - if( 0 == $u && $wgDisableAnonTalk ) { - $utl = ""; + if( 0 == $rc_user && $wgDisableAnonTalk ) { + $userTalkLink = ""; } else { - $utns=$wgLang->getNsText(Namespace::getTalk(Namespace::getUser())); - $utl= $this->makeLink($utns . ":{$ut}", $talkname ); - } - $cr = wfMsg( "currentrev" ); - - $s .= "
    • ({$dlink}) ({$hlink}) . ."; - $M = wfMsg( "minoreditletter" ); - $N = wfMsg( "newpageletter" ); - if ( $isminor ) { $s .= " {$M}"; } - if ( $isnew ) { $s .= "{$N}"; } - $s .= " {$clink}; {$h} . . {$ul}"; - - $blink=""; - if ( ( 0 == $u ) && $wgUser->isSysop() ) { - $blink = $this->makeKnownLink( $wgLang->specialPage( - "Blockip" ), wfMsg( "blocklink" ), "ip={$ut}" ); + $utns=$wgLang->getNsText(NS_USER_TALK); + $userTalkLink= $this->makeLink($utns . ":{$rc_user_text}", $talkname ); + } + # Block link + $blockLink=""; + if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) { + $blockLink = $this->makeKnownLink( $wgLang->specialPage( + "Blockip" ), wfMsg( "blocklink" ), "ip={$rc_user_text}" ); } - if($blink) { - if($utl) $utl .= " | "; - $utl .= $blink; + if($blockLink) { + if($userTalkLink) $userTalkLink .= " | "; + $userTalkLink .= $blockLink; } - if($utl) $s.=" ({$utl})"; + if($userTalkLink) $s.=" ({$userTalkLink})"; - if ( "" != $c && "*" != $c ) { - $s .= " (" . wfEscapeHTML( $c ) . ")"; + # Add comment + if ( "" != $rc_comment && "*" != $rc_comment && $rc_type != RC_MOVE ) { + $s .= " (" . wfEscapeHTML( $rc_comment ) . ")"; } $s .= "
    • \n"; return $s; } - - function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 ) + +# function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 ) + function recentChangesLineNew( $row, $watched = false ) { global $wgTitle, $wgLang, $wgUser; - $rc = new RecentChangesClass ; + # Fill $rc with all the information from the row + $rc = new RCCacheEntry ; + $rc->loadFromRow( $row ); - $d = $wgLang->date( $ts, true); - $s = ""; + # Extract fields from DB into the function scope (rc_xxxx variables) + extract( $rc->mAttribs ); + $curIdEq = "curid=" . $rc_cur_id; + + # If it's a new day, add the headline and flush the cache + $date = $wgLang->date( $rc_timestamp, true); $ret = "" ; - if ( $d != $this->lastdate ) { + if ( $date != $this->lastdate ) { + # Process current cache $ret = $this->recentChangesBlock () ; $this->rc_cache = array() ; - $ret .= "

      {$d}

      \n"; - $this->lastdate = $d; - } - $h = $wgLang->time( $ts, true ); - $t = Title::makeName( $ns, $ttl ); - $clink = $this->makeKnownLink( $t, "" ) ; - if ( $oldid == 0 ) $c2link = $clink ; - else $c2link = $this->makeKnownLink( $t, "" , "oldid={$oldid}" ); - $nt = Title::newFromText( $t ); - - $rc->timestamp = $h ; - $rc->oldid = $oldid ; - $rc->diffid = $diffid ; + $ret .= "

      {$date}

      \n"; + $this->lastdate = $date; + } + + # Make article link + if ( $rc_type == RC_MOVE ) { + $clink = $this->makeKnownLinkObj( $rc->getTitle(), "", "redirect=no" ); + $clink .= " " . wfMsg("movedto") . " "; + $clink .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), "" ); + } else { + $clink = $this->makeKnownLinkObj( $rc->getTitle(), "" ) ; + } + + $time = $wgLang->time( $rc_timestamp, true ); $rc->watched = $watched ; - $rc->isnew = $isnew ; - $rc->isminor = $isminor ; - $rc->secureName = $t ; - $rc->displayName = $nt ; $rc->link = $clink ; - $rc->usercomment = $c ; - $rc->islog = $nt->isLog() ; - - if ( ( $isnew && $oldid == 0 ) || $nt->isLog() ) { - $dlink = wfMsg( "cur" ); + $rc->timestamp = $time; + + # Make "cur" link + if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE) { + $curLink = wfMsg( "cur" ); } else { - $dlink = $this->makeKnownLink( $t, wfMsg( "cur" ), - "diff=0&oldid={$oldid}" ); + $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "cur" ), + "{$curIdEq}&diff=0&oldid={$rc_this_oldid}" ); } - if ( $diffid == 0 || $nt->isLog() ) { - $plink = wfMsg( "last" ); + # Make "last" link + $titleObj = $rc->getTitle(); + if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE ) { + $lastLink = wfMsg( "last" ); } else { - $plink = $this->makeKnownLink( $t, wfMsg( "last" ), - "diff={$oldid}&oldid={$diffid}" ); + $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "last" ), + "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}" ); } - if ( 0 == $u ) { - $ul = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ), - $ut, "target=" . $ut ); - } else { $ul = $this->makeLink( $wgLang->getNsText( - Namespace::getUser() ) . ":{$ut}", $ut ); } - - $rc->userlink = $ul ; - $rc->lastlink = $plink ; - $rc->curlink = $dlink ; + # Make user link (or user contributions for unregistered users) + if ( 0 == $rc_user ) { + $userLink = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ), + $rc_user_text, "target=" . $rc_user_text ); + } else { $userLink = $this->makeLink( $wgLang->getNsText( + Namespace::getUser() ) . ":{$rc_user_text}", $rc_user_text ); } - $utns=$wgLang->getNsText(Namespace::getTalk(Namespace::getUser())); - $talkname=$wgLang->getNsText(Namespace::getTalk(0)); # use the shorter name - $utl= $this->makeLink($utns . ":{$ut}", $talkname ); + $rc->userlink = $userLink ; + $rc->lastlink = $lastLink ; + $rc->curlink = $curLink ; + # Make user talk link + $utns=$wgLang->getNsText(NS_USER_TALK); + $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name + $userTalkLink= $this->makeLink($utns . ":{$rc_user_text}", $talkname ); + global $wgDisableAnonTalk; - if ( ( 0 == $u ) && $wgUser->isSysop() ) { - $blink = $this->makeKnownLink( $wgLang->specialPage( - "Blockip" ), wfMsg( "blocklink" ), "ip={$ut}" ); + if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) { + $blockLink = $this->makeKnownLink( $wgLang->specialPage( + "Blockip" ), wfMsg( "blocklink" ), "ip={$rc_user_text}" ); if( $wgDisableAnonTalk ) - $rc->usertalklink = " ({$blink})"; + $rc->usertalklink = " ({$blockLink})"; else - $rc->usertalklink = " ({$utl} | {$blink})"; + $rc->usertalklink = " ({$userTalkLink} | {$blockLink})"; } else { - if( $wgDisableAnonTalk && ($u == 0) ) + if( $wgDisableAnonTalk && ($rc_user == 0) ) $rc->usertalklink = ""; else - $rc->usertalklink = " ({$utl})"; + $rc->usertalklink = " ({$userTalkLink})"; } - if ( !isset ( $this->rc_cache[$t] ) ) $this->rc_cache[$t] = array() ; - array_push ( $this->rc_cache[$t] , $rc ) ; + # Put accumulated information into the cache, for later display + # Page moves go on their own line + $title = $rc->getTitle(); + $secureName = $title->getPrefixedDBkey(); + if ( $rc_type == RC_MOVE ) { + array_push($this->rc_cache, array($rc) ); + } else { + if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ; + array_push ( $this->rc_cache[$secureName] , $rc ) ; + } return $ret; } + function endImageHistoryList() + { + $s = "
    \n"; + return $s; + } function imageHistoryLine( $iscur, $ts, $img, $u, $ut, $size, $c ) { diff --git a/includes/SpecialMovepage.php b/includes/SpecialMovepage.php index 5ee03133c3..b85f382bbd 100644 --- a/includes/SpecialMovepage.php +++ b/includes/SpecialMovepage.php @@ -299,21 +299,7 @@ class MovePageForm { "old_namespace={$this->ons} AND old_title='{$this->odt}'"; wfQuery( $sql, DB_WRITE, $fname ); - $sql = "UPDATE recentchanges SET ". - "rc_namespace={$this->nns}, rc_title='{$this->ndt}' WHERE ". - "rc_cur_id={$this->oldid}"; - wfQuery( $sql, DB_WRITE, $fname ); - - # FIXME: Here we mark the redirect as 'new' in recentchanges, - # but as old in cur. Is there a reason for this? - $sql = "INSERT INTO recentchanges (rc_namespace,rc_title, - rc_comment,rc_user,rc_user_text,rc_timestamp, - rc_cur_time,rc_cur_id,rc_new) - VALUES ({$this->ons},'{$this->odt}'," . - "'{$mt} \\\"{$this->nft}\\\"','" . - $wgUser->getID() . "','" . wfStrencode( $wgUser->getName() ) . - "','{$now}','{$now}',{$this->newid},1)"; - wfQuery( $sql, DB_WRITE, $fname ); + RecentChange::notifyMove( $now, $this->ot, $this->nt, $wgUser, $mt ); # The only link from here should be the old redirect @@ -360,10 +346,11 @@ class MovePageForm { wfQuery( $sql, DB_WRITE, $fname ); $wgLinkCache->clearLink( $this->nft ); + $comment = "{$mt} \"{$this->nft}\""; + $encComment = wfStrencode( $comment ); $common = "{$this->ons},'{$this->odt}'," . - "'{$mt} \\\"{$this->nft}\\\"','" . - $wgUser->getID() . "','" . wfStrencode( $wgUser->getName() ) . - "','{$now}'"; + "'$encComment','" .$wgUser->getID() . "','" . + wfStrencode( $wgUser->getName() ) ."','{$now}'"; $sql = "INSERT INTO cur (cur_namespace,cur_title," . "cur_comment,cur_user,cur_user_text,cur_timestamp,inverse_timestamp," . "cur_touched,cur_text,cur_is_redirect,cur_is_new) " . @@ -377,17 +364,7 @@ class MovePageForm { "old_namespace={$this->ons} AND old_title='{$this->odt}'"; wfQuery( $sql, DB_WRITE, $fname ); - $sql = "UPDATE recentchanges SET ". - "rc_namespace={$this->nns}, rc_title='{$this->ndt}' WHERE ". - "rc_namespace={$this->ons} AND rc_title='{$this->odt}'"; - wfQuery( $sql, DB_WRITE, $fname ); - - $sql = "INSERT INTO recentchanges (rc_namespace,rc_title, - rc_comment,rc_user,rc_user_text,rc_timestamp, - rc_cur_time,rc_cur_id,rc_new) - VALUES ({$common},'{$now}',{$this->newid},1)"; - wfQuery( $sql, DB_WRITE, $fname ); - + RecentChange::notifyMove( $now, $this->ot, $this->nt, $wgUser, $comment ); Article::onArticleCreate( $this->nt ); $sql = "UPDATE links SET l_from='{$this->nft}' WHERE l_from='{$this->oft}'"; diff --git a/includes/SpecialRecentchanges.php b/includes/SpecialRecentchanges.php index 9fce1a5005..f7753551ba 100644 --- a/includes/SpecialRecentchanges.php +++ b/includes/SpecialRecentchanges.php @@ -80,8 +80,7 @@ function wfSpecialRecentchanges( $par ) } $uid = $wgUser->getID(); - $sql2 = "SELECT rc_cur_id,rc_namespace,rc_title,rc_user,rc_new," . - "rc_comment,rc_user_text,rc_timestamp,rc_minor,rc_this_oldid,rc_last_oldid,rc_bot" . ($uid ? ",wl_user" : "") . " FROM recentchanges " . + $sql2 = "SELECT recentchanges.*" . ($uid ? ",wl_user" : "") . " FROM recentchanges " . ($uid ? "LEFT OUTER JOIN watchlist ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace & 65534 " : "") . "WHERE rc_timestamp > '{$cutoff}' {$hidem} " . "ORDER BY rc_timestamp DESC LIMIT {$limit}"; @@ -108,27 +107,15 @@ function wfSpecialRecentchanges( $par ) $s = $sk->beginRecentChangesList(); while ( $limit ) { - if ( ( 0 == $count1 ) ) { break; } - - $ts = $obj1->rc_timestamp; - $u = $obj1->rc_user; - $ut = $obj1->rc_user_text; - $ns = $obj1->rc_namespace; - $ttl = $obj1->rc_title; - $com = $obj1->rc_comment; - $me = ( $obj1->rc_minor > 0 ); - $new = ( $obj1->rc_new > 0 ); - $watched = ($obj1->wl_user > 0); - $oldid = $obj1->rc_this_oldid ; - $diffid = $obj1->rc_last_oldid ; - - $obj1 = wfFetchObject( $res ); - --$count1; - if ( ! ( $hideminor && $me ) ) { - $s .= $sk->recentChangesLine( $ts, $u, $ut, $ns, $ttl, - $com, $me, $new, $watched, $oldid , $diffid ); + if ( ( 0 == $count1 ) ) { + break; + } + if ( ! ( $hideminor && $obj1->rc_minor ) ) { + $s .= $sk->recentChangesLine( $obj1, $obj1->wl_user ); --$limit; } + $obj1 = wfFetchObject( $res ); + --$count1; } $s .= $sk->endRecentChangesList(); diff --git a/includes/SpecialUserlogin.php b/includes/SpecialUserlogin.php index b18e501a1c..7daa17ca7c 100644 --- a/includes/SpecialUserlogin.php +++ b/includes/SpecialUserlogin.php @@ -91,7 +91,7 @@ function wfSpecialUserlogin() /* private */ function addNewAccountInternal() { global $wgUser, $wgOut, $wpPassword, $wpRetype, $wpName, $wpRemember; - global $wpEmail; + global $wpEmail, $wgMaxNameChars; if (!$wgUser->isAllowedToCreateAccount()) { userNotPrivilegedMessage(); @@ -105,7 +105,8 @@ function wfSpecialUserlogin() $wpName = trim( $wpName ); if ( ( "" == $wpName ) || preg_match( "/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/", $wpName ) || - (strpos( $wpName, "/" ) !== false) ) + (strpos( $wpName, "/" ) !== false) || + (strlen( $wpName ) > $wgMaxNameChars) ) { mainLoginForm( wfMsg( "noname" ) ); return; diff --git a/includes/Title.php b/includes/Title.php index 5955567c2e..c245bf6c00 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -88,6 +88,21 @@ class Title { return NULL; } } + + # Create a title from a cur id + # This is inefficiently implemented + function newFromID( $id ) + { + $fname = "Title::newFromID"; + $row = wfGetArray( "cur", array( "cur_namespace", "cur_title" ), + array( "cur_id" => $id ), $fname ); + if ( $row !== false ) { + $title = Title::makeTitle( $row->cur_namespace, $row->cur_title ); + } else { + $title = NULL; + } + return $title; + } function nameOf( $id ) { diff --git a/install-utils.inc b/install-utils.inc index f9842476a1..d78b7b02b5 100644 --- a/install-utils.inc +++ b/install-utils.inc @@ -76,7 +76,7 @@ function replacevars( $ins ) { # # Read and execute SQL commands from a file # -function dbsource( $fname, $conn = false ) { +function dbsource( $fname, $database = false ) { $fp = fopen( $fname, "r" ); if ( false === $fp ) { print "Could not open \"{$fname}\".\n"; @@ -103,8 +103,8 @@ function dbsource( $fname, $conn = false ) { if ( $done ) { $cmd = replacevars( $cmd ); - if( $conn ) - $res = mysql_query( $cmd, $conn ); + if( $database ) + $res = $database->query( $cmd ); else $res = mysql_query( $cmd ); @@ -120,7 +120,7 @@ function dbsource( $fname, $conn = false ) { fclose( $fp ); } - +# Obsolete, use Database::fieldExists() function field_exists( $table, $field ) { $fname = "Update script: field_exists"; $res = wfQuery( "DESCRIBE $table", $fname ); @@ -135,7 +135,7 @@ function field_exists( $table, $field ) { return $found; } - +# Obsolete Database::tableExists() function table_exists( $db ) { global $wgDBname; $res = mysql_list_tables( $wgDBname ); @@ -149,6 +149,7 @@ function table_exists( $db ) { return false; } +# Obsolete, use Database:fieldInfo() function field_info( $table, $field ) { $res = mysql_query( "SELECT * FROM $table LIMIT 1" ); $n = mysql_num_fields( $res ); diff --git a/install.php b/install.php index 552c6036f8..1348d95e28 100644 --- a/install.php +++ b/install.php @@ -96,8 +96,8 @@ print "\nYou should have already created a root password for the database.\n" . $rootpw = readconsole(); -$rconn = mysql_connect( $wgDBserver, "root", $rootpw ); -if ( false === $rconn ) { +$wgDatabase = Database::newFromParams( $wgDBserver, "root", $rootpw, "", 1 ); +if ( !$wgDatabase->isOpen() ) { print "Could not connect to database on \"{$wgDBserver}\" as root.\n"; exit(); } @@ -110,18 +110,18 @@ $wgTitle = Title::newFromText( "Installation script" ); # Now do the actual database creation # print "Creating database...\n"; -dbsource( "./maintenance/database.sql", $rconn ); +dbsource( "./maintenance/database.sql", $wgDatabase ); -mysql_select_db( $wgDBname, $rconn ); -dbsource( "./maintenance/tables.sql", $rconn ); -dbsource( "./maintenance/users.sql", $rconn ); -dbsource( "./maintenance/initialdata.sql", $rconn ); -dbsource( "./maintenance/interwiki.sql", $rconn ); +$wgDatabase->selectDB( $wgDBname ); +dbsource( "./maintenance/tables.sql", $wgDatabase ); +dbsource( "./maintenance/users.sql", $wgDatabase ); +dbsource( "./maintenance/initialdata.sql", $wgDatabase ); +dbsource( "./maintenance/interwiki.sql", $wgDatabase ); populatedata(); # Needs internationalized messages print "Adding indexes...\n"; -dbsource( "./maintenance/indexes.sql", $rconn ); +dbsource( "./maintenance/indexes.sql", $wgDatabase ); print "Done.\nBrowse \"{$wgServer}{$wgScript}\" to test.\n"; exit(); @@ -148,18 +148,18 @@ function makedirectory( $d ) { function populatedata() { - global $wgDBadminpassword; + global $wgDBadminpassword, $wgDatabase; $fname = "Installation script: populatedata()"; $sql = "DELETE FROM site_stats"; - wfQuery( $sql, DB_WRITE, $fname ); + $wgDatabase->query( $sql, $fname ); $sql = "INSERT INTO site_stats (ss_row_id,ss_total_views," . "ss_total_edits,ss_good_articles) VALUES (1,0,0,0)"; - wfQuery( $sql, DB_WRITE, $fname ); + $wgDatabase->query( $sql, $fname ); $sql = "DELETE FROM user"; - wfQuery( $sql, DB_WRITE, $fname ); + $wgDatabase->query( $sql, $fname ); $u = User::newFromName( "WikiSysop" ); if ( 0 == $u->idForName() ) { @@ -182,7 +182,7 @@ function populatedata() { $dlp = addslashes( wfMsgNoDB( "dellogpage" ) ); $sql = "DELETE FROM cur"; - wfQuery( $sql, DB_WRITE, $fname ); + $wgDatabase->query( $sql, $fname ); $now = wfTimestampNow(); $won = wfInvertTimestamp( $now ); @@ -190,19 +190,19 @@ function populatedata() { $sql = "INSERT INTO cur (cur_namespace,cur_title,cur_text," . "cur_restrictions,cur_timestamp,inverse_timestamp,cur_touched) VALUES ({$wns},'{$ulp}','" . wfStrencode( wfMsg( "uploadlogpagetext" ) ) . "','sysop','$now','$won','$now')"; - wfQuery( $sql, DB_WRITE, $fname ); + $wgDatabase->query( $sql, $fname ); $sql = "INSERT INTO cur (cur_namespace,cur_title,cur_text," . "cur_restrictions,cur_timestamp,inverse_timestamp,cur_touched) VALUES ({$wns},'{$dlp}','" . wfStrencode( wfMsg( "dellogpagetext" ) ) . "','sysop','$now','$won','$now')"; - wfQuery( $sql, DB_WRITE, $fname ); + $wgDatabase->query( $sql, $fname ); $titleobj = Title::newFromText( wfMsgNoDB( "mainpage" ) ); $title = $titleobj->getDBkey(); $sql = "INSERT INTO cur (cur_namespace,cur_title,cur_text,cur_timestamp,inverse_timestamp,cur_touched) " . "VALUES (0,'$title','" . wfStrencode( wfMsg( "mainpagetext" ) ) . "','$now','$won','$now')"; - wfQuery( $sql, DB_WRITE, $fname ); + $wgDatabase->query( $sql, $fname ); initialiseMessages(); } diff --git a/maintenance/archives/patch-rc_type.sql b/maintenance/archives/patch-rc_type.sql new file mode 100644 index 0000000000..abe11f98d0 --- /dev/null +++ b/maintenance/archives/patch-rc_type.sql @@ -0,0 +1,6 @@ +-- recentchanges improvements -- + +ALTER TABLE recentchanges + ADD rc_type tinyint(3) unsigned NOT NULL default '0', + ADD rc_moved_to_ns tinyint(3) unsigned NOT NULL default '0', + ADD rc_moved_to_title varchar(255) binary NOT NULL default ''; diff --git a/maintenance/tables.sql b/maintenance/tables.sql index 9d9b454002..8a9d79a729 100644 --- a/maintenance/tables.sql +++ b/maintenance/tables.sql @@ -164,7 +164,10 @@ CREATE TABLE recentchanges ( rc_new tinyint(3) unsigned NOT NULL default '0', rc_cur_id int(10) unsigned NOT NULL default '0', rc_this_oldid int(10) unsigned NOT NULL default '0', - rc_last_oldid int(10) unsigned NOT NULL default '0' + rc_last_oldid int(10) unsigned NOT NULL default '0', + rc_type tinyint(3) unsigned NOT NULL default '0', + rc_moved_to_ns tinyint(3) unsigned NOT NULL default '0', + rc_moved_to_title varchar(255) binary NOT NULL default '', ) TYPE=MyISAM PACK_KEYS=1; DROP TABLE IF EXISTS watchlist; diff --git a/update.php b/update.php index 9e87d3af5c..477de0f752 100644 --- a/update.php +++ b/update.php @@ -41,22 +41,27 @@ $wgTitle = Title::newFromText( "Update script" ); # # Check the database for things that need to be fixed... # - print "Checking database for necessary updates...\n"; +print "Checking database for necessary updates...\n"; - $rconn = mysql_connect( $wgDBserver, $wgDBadminuser, $wgDBadminpassword ); - mysql_select_db( $wgDBname ); +$wgDatabase = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname, + 1, false, true, false); +if ( !$wgDatabase->isOpen() ) { + print "Unable to connect to database: " . $wgDatabase->lastError() . "\n"; + exit(); +} - do_revision_updates(); - - do_ipblocks_update(); - do_interwiki_update(); - do_index_update(); - do_linkscc_update(); - do_hitcounter_update(); +do_revision_updates(); + +do_ipblocks_update(); +do_interwiki_update(); +do_index_update(); +do_linkscc_update(); +do_hitcounter_update(); +do_recentchanges_update(); - initialiseMessages(); +initialiseMessages(); - mysql_close( $rconn ); +$wgDatabase->close(); print "Done.\n"; exit(); @@ -110,6 +115,7 @@ function do_revision_updates() { } function update_passwords() { + global $wgDatabase; $fname = "Update script: update_passwords()"; print "\nIt appears that you need to update the user passwords in your\n" . "database. If you have already done this (if you've run this update\n" . @@ -121,25 +127,26 @@ function update_passwords() { if ( ! ( "Y" == $resp{0} || "y" == $resp{0} ) ) { return; } $sql = "SELECT user_id,user_password FROM user"; - $source = wfQuery( $sql, DB_READ, fname ); + $source = $wgDatabase->query( $sql, $fname ); - while ( $row = mysql_fetch_object( $source ) ) { + while ( $row = $wgDatabase->fetchObject( $source ) ) { $id = $row->user_id; $oldpass = $row->user_password; $newpass = md5( "{$id}-{$oldpass}" ); $sql = "UPDATE user SET user_password='{$newpass}' " . "WHERE user_id={$id}"; - wfQuery( $sql, DB_WRITE, $fname ); + $wgDatabase->query( $sql, $fname ); } } function do_ipblocks_update() { - if ( wfFieldExists( "ipblocks", "ipb_id" ) ) { + global $wgDatabase; + if ( $wgDatabase->fieldExists( "ipblocks", "ipb_id" ) ) { echo "...ipblocks table is up to date.\n"; } else { echo "Updating ipblocks table... "; - dbsource( "maintenance/archives/patch-ipblocks.sql" ); + dbsource( "maintenance/archives/patch-ipblocks.sql", $wgDatabase ); echo "ok\n"; } } @@ -147,7 +154,8 @@ function do_ipblocks_update() { function do_interwiki_update() { # Check that interwiki table exists; if it doesn't source it - if( table_exists( "interwiki" ) ) { + global $wgDatabase; + if( $wgDatabase->tableExists( "interwiki" ) ) { echo "...already have interwiki table\n"; return true; } @@ -161,7 +169,8 @@ function do_interwiki_update() { function do_index_update() { # Check that proper indexes are in place - $meta = field_info( "recentchanges", "rc_timestamp" ); + global $wgDatabase; + $meta = $wgDatabase->field_info( "recentchanges", "rc_timestamp" ); if( $meta->multiple_key == 0 ) { echo "Updating indexes to 20031107: "; dbsource( "maintenance/archives/patch-indexes.sql" ); @@ -174,27 +183,35 @@ function do_index_update() { function do_linkscc_update() { // Create linkscc if necessary - global $rconn; + global $wgDatabase; if( table_exists( "linkscc" ) ) { echo "...have linkscc table.\n"; } else { echo "Adding linkscc table... "; - dbsource( "maintenance/archives/patch-linkscc.sql" ); + dbsource( "maintenance/archives/patch-linkscc.sql", $wgDatabase ); echo "ok\n"; } } function do_hitcounter_update() { // Create hitcounter if necessary - global $rconn; - if( table_exists( "hitcounter" ) ) { + global $wgDatabase; + if( $wgDatabase->tableExists( "hitcounter" ) ) { echo "...have hitcounter table.\n"; } else { echo "Adding hitcounter table... "; - dbsource( "maintenance/archives/patch-hitcounter.sql" ); + dbsource( "maintenance/archives/patch-hitcounter.sql", $wgDatabase ); echo "ok\n"; } } +function do_recentchanges_update() { + global $wgDatabase; + if ( !$wgDatabase->fieldExists( "recentchanges", "rc_type" ) ) { + echo "Adding rc_type, rc_moved_to_ns, rc_moved_to_title..."; + dbsource( "maintenance/archives/patch-rc_type.sql" , $wgDatabase ); + echo "ok\n"; + } +} ?> diff --git a/wiki.phtml b/wiki.phtml index 8071dfbdde..86605c8fb6 100644 --- a/wiki.phtml +++ b/wiki.phtml @@ -32,7 +32,11 @@ if ( function_exists( "getallheaders" ) ) { # Query string fields # global $action, $title, $search, $go, $target, $printable; -global $returnto, $diff, $oldid; +global $returnto, $diff, $oldid, $curid; + +# Placeholders in case of DB error +$wgTitle = Title::newFromText( wfMsg( "badtitle" ) ); +$wgArticle = new Article($wgTitle); $action = strtolower( trim( $action ) ); if ( "" == $action ) { $action = "view"; } @@ -40,6 +44,9 @@ if ( "yes" == $printable ) { $wgOut->setPrintable(); } if ( "" == $title && "delete" != $action ) { $wgTitle = Title::newFromText( wfMsg( "mainpage" ) ); +} elseif ( $curid ) { + # URLs like this are generated by RC, because rc_title isn't always accurate + $wgTitle = Title::newFromID( $curid ); } else { $wgTitle = Title::newFromURL( $title ); } -- 2.20.1
-{$otitle} -{$ntitle}