Josh Cogliati wrote:
Attached is a patch for a feature that creates an info
page with
information about a page. Currently, it is the number of people
watching the page, the number of edits, and the number of talk edits,
the number of authors of the article and the number of authors on the
talk page.
Thanks for your work! However, I have a few comments about it :)
- Your feature displays bogus information when the page and/or its talk
page don't exist.
- You forgot to display the total number of edits of the talk page, even
though you added a string for it in Language.php. :)
- Some of your queries were pretty inefficient: At one point, you
retrieved a potentially large number of rows, just to count them.
- Your patch uses "UNION". MySQL 3 doesn't support that.
- The text you added to Language.php was a bit weird (why did you
capitalise everything?).
I fixed all of this in one fell swoop, see attachment :)
Sorry about the whitespace changes in my patch, but there aren't many,
they don't make the patch unreadable, and committing them once will make
them never occur again :)
Timwi
Index: index.php
===================================================================
RCS file: /cvsroot/wikipedia/phase3/index.php,v
retrieving revision 1.35
diff -u -r1.35 index.php
--- index.php 28 Jun 2004 17:46:49 -0000 1.35
+++ index.php 8 Jul 2004 11:04:20 -0000
@@ -108,6 +108,7 @@
case "rollback":
case "protect":
case "unprotect":
+ case "info":
$wgArticle->$action();
break;
case "print":
Index: includes/Article.php
===================================================================
RCS file: /cvsroot/wikipedia/phase3/includes/Article.php,v
retrieving revision 1.175
diff -u -r1.175 Article.php
--- includes/Article.php 28 Jun 2004 20:24:23 -0000 1.175
+++ includes/Article.php 8 Jul 2004 11:04:20 -0000
@@ -16,12 +16,12 @@
/* 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;
@@ -62,7 +62,7 @@
}
return $text;
}
-
+
/* static */ function compressRevisionText( &$text ) {
global $wgCompressRevisions;
if( !$wgCompressRevisions ) {
@@ -75,7 +75,7 @@
$text = gzdeflate( $text );
return 'gzip';
}
-
+
# Returns the text associated with a "link" type old table row
/* static */ function followLink( $link ) {
# Split the link into fields and values
@@ -119,7 +119,7 @@
global $wgLoadBalancer;
$fname = 'fetchFromLocation';
wfProfileIn( $fname );
-
+
$p = strpos( $location, ':' );
if ( $p === false ) {
wfProfileOut( $fname );
@@ -132,7 +132,7 @@
case 'mysql':
# MySQL locations are specified by
mysql://<machineID>/<dbname>/<tblname>/<index>
# Machine ID 0 is the current connection
- if ( preg_match(
'/^mysql:\/\/(\d+)\/([A-Za-z_]+)\/([A-Za-z_]+)\/([A-Za-z_]+)$/',
+ if ( preg_match(
'/^mysql:\/\/(\d+)\/([A-Za-z_]+)\/([A-Za-z_]+)\/([A-Za-z_]+)$/',
$location, $matches ) ) {
$machineID = $matches[1];
$dbName = $matches[2];
@@ -144,11 +144,11 @@
} else {
# Alternate connection
$db =& $wgLoadBalancer->getConnection( $machineID );
-
+
if ( array_key_exists( $machineId, $wgKnownMysqlServers ) ) {
# Try to open, return false on failure
$params = $wgKnownDBServers[$machineId];
- $db = Database::newFromParams( $params['server'], $params['user'],
$params['password'],
+ $db = Database::newFromParams( $params['server'], $params['user'],
$params['password'],
$dbName, 1, false, true, true );
}
}
@@ -244,15 +244,15 @@
}
}
}
-
+
# This function returns the text of a section, specified by a number ($section).
- # A section is text under a heading like == Heading == or <h1>Heading</h1>,
or
+ # A section is text under a heading like == Heading == or <h1>Heading</h1>,
or
# the first section before any such heading (section 0).
#
# If a section contains subsections, these are also returned.
#
function getSection($text,$section) {
-
+
# strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
# comments to be stripped as well)
$striparray=array();
@@ -273,23 +273,23 @@
$headline=$secs[$section*2-1];
preg_match( '/^(=+).*?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?'
. '>/mi',$headline,$matches);
$hlevel=$matches[1];
-
+
# translate wiki heading into level
if(strpos($hlevel,'=')!==false) {
- $hlevel=strlen($hlevel);
+ $hlevel=strlen($hlevel);
}
-
+
$rv=$headline. $secs[$section*2];
$count=$section+1;
-
+
$break=false;
while(!empty($secs[$count*2-1]) && !$break) {
-
+
$subheadline=$secs[$count*2-1];
preg_match( '/^(=+).*?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?'
. '>/mi',$subheadline,$matches);
$subhlevel=$matches[1];
if(strpos($subhlevel,'=')!==false) {
- $subhlevel=strlen($subhlevel);
+ $subhlevel=strlen($subhlevel);
}
if($subhlevel > $hlevel) {
$rv.=$subheadline.$secs[$count*2];
@@ -298,7 +298,7 @@
$break=true;
}
$count++;
-
+
}
}
# reinsert stripped tags
@@ -308,7 +308,7 @@
return $rv;
}
-
+
# Load the revision (including cur_text) into this object
function loadContent( $noredir = false )
@@ -321,21 +321,21 @@
if ( $this->mContentLoaded ) return;
$fname = 'Article::loadContent';
-
- # Pre-fill content with error message so that if something
+
+ # 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 = $this->mTitle->getPrefixedText();
+ if ( isset( $oldid ) ) {
+ $oldid = IntVal( $oldid );
$t .= ",oldid={$oldid}";
- }
- if ( isset( $redirect ) ) {
- $redirect = ($redirect == 'no') ? 'no' : 'yes';
- $t .= ",redirect={$redirect}";
- }
+ }
+ if ( isset( $redirect ) ) {
+ $redirect = ($redirect == 'no') ? 'no' : 'yes';
+ $t .= ",redirect={$redirect}";
+ }
$this->mContent = wfMsg( 'missingarticle', $t );
-
+
if ( ! $oldid ) { # Retrieve current version
$id = $this->getID();
if ( 0 == $id ) return;
@@ -345,8 +345,8 @@
"FROM cur WHERE cur_id={$id}";
wfDebug( "$sql\n" );
$res = wfQuery( $sql, DB_READ, $fname );
- if ( 0 == wfNumRows( $res ) ) {
- return;
+ if ( 0 == wfNumRows( $res ) ) {
+ return;
}
$s = wfFetchObject( $res );
@@ -361,7 +361,7 @@
# Gotta hand redirects to special pages differently:
# Fill the HTTP response "Location" header and ignore
# the rest of the page we're on.
-
+
if ( $rt->getInterwiki() != '' ) {
$wgOut->redirect( $rt->getFullURL() ) ;
return;
@@ -375,7 +375,7 @@
$sql = 'SELECT cur_text,cur_timestamp,cur_user,cur_user_text,cur_comment,'
.
"cur_counter,cur_restrictions,cur_touched FROM cur WHERE
cur_id={$rid}";
$res = wfQuery( $sql, DB_READ, $fname );
-
+
if ( 0 != wfNumRows( $res ) ) {
$this->mRedirectedFrom = $this->mTitle->getPrefixedText();
$this->mTitle = $rt;
@@ -434,9 +434,9 @@
return $this->mContent;
}
$this->mContent = false;
-
+
$fname = 'Article::loadContent';
-
+
if ( ! $oldid ) { # Retrieve current version
$id = $this->getID();
if ( 0 == $id ) {
@@ -447,8 +447,8 @@
'cur_text,cur_timestamp,cur_user,cur_counter,cur_restrictions,cur_touched '
.
"FROM cur WHERE cur_id={$id}";
$res = wfQuery( $sql, DB_READ, $fname );
- if ( 0 == wfNumRows( $res ) ) {
- return false;
+ if ( 0 == wfNumRows( $res ) ) {
+ return false;
}
$s = wfFetchObject( $res );
@@ -464,7 +464,7 @@
$sql = 'SELECT cur_text,cur_timestamp,cur_user,' .
"cur_counter,cur_restrictions,cur_touched FROM cur WHERE
cur_id={$rid}";
$res = wfQuery( $sql, DB_READ, $fname );
-
+
if ( 0 != wfNumRows( $res ) ) {
$this->mRedirectedFrom = $this->mTitle->getPrefixedText();
$this->mTitle = $rt;
@@ -488,8 +488,8 @@
$sql = "SELECT old_text,old_timestamp,old_user,old_flags FROM $oldtable " .
"WHERE old_id={$oldid}";
$res = wfQuery( $sql, DB_READ, $fname );
- if ( 0 == wfNumRows( $res ) ) {
- return false;
+ if ( 0 == wfNumRows( $res ) ) {
+ return false;
}
$s = wfFetchObject( $res );
@@ -526,7 +526,7 @@
function isCountable( $text )
{
global $wgUseCommaCount, $wgMwRedir;
-
+
if ( 0 != $this->mTitle->getNamespace() ) { return 0; }
if ( $wgMwRedir->matchStart( $text ) ) { return 0; }
$token = ($wgUseCommaCount ? ',' : '[[' );
@@ -592,7 +592,7 @@
$fname = 'Article::getContributors';
# XXX: this is expensive; cache this info somewhere.
-
+
$title = $this->mTitle;
$contribs = array();
@@ -602,8 +602,8 @@
' FROM old LEFT JOIN user ON old.old_user = user.user_id '
.
' WHERE old.old_namespace = ' . $title->getNamespace() .
' AND old.old_title = "' . $title->getDBkey() .
'"' .
- ' AND old.old_user != ' . $this->getUser() .
- ' GROUP BY old.old_user ' .
+ ' AND old.old_user != ' . $this->getUser() .
+ ' GROUP BY old.old_user ' .
' ORDER BY timestamp DESC ';
if ($limit > 0) {
@@ -611,16 +611,16 @@
}
$res = wfQuery($sql, DB_READ, $fname);
-
+
while ( $line = wfFetchObject( $res ) ) {
$contribs[] = array($line->old_user, $line->old_user_text,
$line->user_real_name);
}
-
+
wfFreeResult($res);
-
+
return $contribs;
}
-
+
# This is the default action of the script: just view the page of
# the given title.
@@ -628,7 +628,7 @@
{
global $wgUser, $wgOut, $wgLang, $wgRequest;
global $wgLinkCache, $IP, $wgEnableParserCache;
-
+
$fname = 'Article::view';
wfProfileIn( $fname );
@@ -660,14 +660,14 @@
return;
}
}
-
+
# Should the parser cache be used?
if ( $wgEnableParserCache && intval($wgUser->getOption(
'stubthreshold' )) == 0 && empty( $oldid ) ) {
$pcache = true;
} else {
$pcache = false;
}
-
+
$outputDone = false;
if ( $pcache ) {
if ( $wgOut->tryParserCache( $this, $wgUser ) ) {
@@ -677,14 +677,14 @@
if ( !$outputDone ) {
$text = $this->getContent( false ); # May change mTitle by following a redirect
-
+
# Another whitelist check in case oldid or redirects are altering the title
if ( !$this->mTitle->userCanRead() ) {
$wgOut->loginToUse();
$wgOut->output();
exit;
}
-
+
# We're looking at an old revision
@@ -698,8 +698,8 @@
'redirect=no' );
$s = wfMsg( 'redirectedfrom', $redir );
$wgOut->setSubtitle( $s );
-
- # Can't cache redirects
+
+ # Can't cache redirects
$pcache = false;
}
@@ -707,8 +707,8 @@
# wrap user css and user js in pre and don't parse
# XXX: use $this->mTitle->usCssJsSubpage() when php is fixed/ a workaround is
found
- if (
- $this->mTitle->getNamespace() == Namespace::getUser() &&
+ if (
+ $this->mTitle->getNamespace() == Namespace::getUser() &&
preg_match('/\\/[\\w]+\\.(css|js)$/', $this->mTitle->getDBkey())
) {
$wgOut->addWikiText( wfMsg('clearyourcache'));
@@ -720,7 +720,7 @@
}
}
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
-
+
# Add link titles as META keywords
$wgOut->addMetaTags() ;
@@ -737,7 +737,7 @@
{
global $wgOut, $wgUser, $wgLinkCache, $wgMwRedir;
global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer, $wgIsPg, $wgIsMySQL;
-
+
$fname = 'Article::insertNewArticle';
$this->mCountAdjustment = $this->isCountable( $text );
@@ -752,7 +752,7 @@
$won = wfInvertTimestamp( $now );
wfSeedRandom();
$rand = number_format( mt_rand() / mt_getrandmax(), 12, '.', '' );
-
+
if ($wgIsPg) {
$cur_id_column="cur_id,";
$cur_id=wfGetSQL(""," nextval('cur_cur_id_seq')");
@@ -780,20 +780,20 @@
Article::onArticleCreate( $this->mTitle );
RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary );
-
- if ($watchthis) {
- if(!$this->mTitle->userIsWatching()) $this->watch();
+
+ if ($watchthis) {
+ if(!$this->mTitle->userIsWatching()) $this->watch();
} else {
if ( $this->mTitle->userIsWatching() ) {
$this->unwatch();
}
}
-
+
# The talk page isn't in the regular link tables, so we need to update manually:
$talkns = $ns ^ 1; # talk -> normal; normal -> talk
$sql = "UPDATE cur set cur_touched='$now' WHERE cur_namespace=$talkns AND
cur_title='" . wfStrencode( $ttl ) . "'";
wfQuery( $sql, DB_WRITE );
-
+
# standard deferred updates
$this->editUpdates( $text );
@@ -804,7 +804,7 @@
/* Side effects: loads last edit */
function getTextOfLastEditWithSectionReplacedOrAdded($section, $text, $summary =
''){
$this->loadLastEdit();
- $oldtext = $this->getContent( true );
+ $oldtext = $this->getContent( true );
if ($section != '') {
if($section=='new') {
if($summary) $subject="== {$summary} ==\n\n";
@@ -825,10 +825,10 @@
$secs=preg_split('/(^=+.*?=+|^<h[1-6].*?' .
'>.*?<\/h[1-6].*?' . '>)/mi',
$oldtext,-1,PREG_SPLIT_DELIM_CAPTURE);
$secs[$section*2]=$text."\n\n"; // replace with edited
-
+
# section 0 is top (intro) section
- if($section!=0) {
-
+ if($section!=0) {
+
# headline of old section - we need to go through this section
# to determine if there are any subsections that now need to
# be erased, as the mother section has been replaced with
@@ -836,23 +836,23 @@
$headline=$secs[$section*2-1];
preg_match( '/^(=+).*?=+|^<h([1-6]).*?' .
'>.*?<\/h[1-6].*?' . '>/mi',$headline,$matches);
$hlevel=$matches[1];
-
+
# determine headline level for wikimarkup headings
if(strpos($hlevel,'=')!==false) {
- $hlevel=strlen($hlevel);
+ $hlevel=strlen($hlevel);
}
-
+
$secs[$section*2-1]=''; // erase old headline
$count=$section+1;
$break=false;
while(!empty($secs[$count*2-1]) && !$break) {
-
+
$subheadline=$secs[$count*2-1];
preg_match(
'/^(=+).*?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?' .
'>/mi',$subheadline,$matches);
$subhlevel=$matches[1];
if(strpos($subhlevel,'=')!==false) {
- $subhlevel=strlen($subhlevel);
+ $subhlevel=strlen($subhlevel);
}
if($subhlevel > $hlevel) {
// erase old subsections
@@ -863,16 +863,16 @@
$break=true;
}
$count++;
-
+
}
-
+
}
$text=join('',$secs);
# reinsert the stuff that we stripped out earlier
- $text=$parser->unstrip($text,$striparray);
- $text=$parser->unstripNoWiki($text,$striparray);
+ $text=$parser->unstrip($text,$striparray);
+ $text=$parser->unstripNoWiki($text,$striparray);
}
-
+
}
return $text;
}
@@ -886,7 +886,7 @@
$fname = 'Article::updateArticle';
if ( $this->mMinorEdit ) { $me1 = 1; } else { $me1 = 0; }
- if ( $minor && $wgUser->getID() ) { $me2 = 1; } else { $me2 = 0; }
+ if ( $minor && $wgUser->getID() ) { $me2 = 1; } else { $me2 = 0; }
if ( preg_match( "/^((" . $wgMwRedir->getBaseRegex() .
')[^\\n]+)/i', $text, $m ) ) {
$redir = 1;
$text = $m[1] . "\n"; # Remove all content but redirect
@@ -894,7 +894,7 @@
else { $redir = 0; }
$text = $this->preSaveTransform( $text );
-
+
# Update article, but only if changed.
if( $wgDBtransactions ) {
@@ -918,7 +918,7 @@
"WHERE cur_id=" . $this->getID() .
" AND cur_timestamp='" . $this->getTimestamp() .
"'";
$res = wfQuery( $sql, DB_WRITE, $fname );
-
+
if( wfAffectedRows() == 0 ) {
/* Belated edit conflict! Run away!! */
return false;
@@ -926,7 +926,7 @@
# This overwrites $oldtext if revision compression is on
$flags = Article::compressRevisionText( $oldtext );
-
+
$oldtable=$wgIsPg?'"old"':'old';
if ($wgIsPg) {
$oldtable='"old"';
@@ -956,7 +956,7 @@
$oldid = $wgIsPg?$old_id:wfInsertId( $res );
$bot = (int)($wgUser->isBot() || $forceBot);
- RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary,
+ RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary,
$oldid, $this->getTimestamp(), $bot );
Article::onArticleEdit( $this->mTitle );
}
@@ -965,9 +965,9 @@
$sql = 'COMMIT';
wfQuery( $sql, DB_WRITE );
}
-
- if ($watchthis) {
- if (!$this->mTitle->userIsWatching()) $this->watch();
+
+ if ($watchthis) {
+ if (!$this->mTitle->userIsWatching()) $this->watch();
} else {
if ( $this->mTitle->userIsWatching() ) {
$this->unwatch();
@@ -975,8 +975,8 @@
}
# standard deferred updates
$this->editUpdates( $text );
-
-
+
+
$urls = array();
# Template namespace
# Purge all articles linking here
@@ -989,7 +989,7 @@
}
}
}
-
+
# Squid updates
if ( $wgUseSquid ) {
$urls = array_merge( $urls, $this->mTitle->getSquidURLs() );
@@ -1015,7 +1015,7 @@
$wgLinkCache->preFill( $this->mTitle );
$wgLinkCache->clear();
- # Now update the link cache by parsing the text
+ # Now update the link cache by parsing the text
$wgOut = new OutputPage();
$wgOut->addWikiText( $text );
@@ -1178,16 +1178,16 @@
return $this->protect( '' );
}
- # UI entry point for page deletion
+ # UI entry point for page deletion
function delete()
{
global $wgUser, $wgOut, $wgMessageCache, $wgRequest, $wgIsPg;
$fname = 'Article::delete';
$confirm = $wgRequest->getBool( 'wpConfirm' ) &&
$wgRequest->wasPosted();
$reason = $wgRequest->getText( 'wpReason' );
-
+
# This code desperately needs to be totally rewritten
-
+
# Check permissions
if ( ( ! $wgUser->isSysop() ) ) {
$wgOut->sysopRequired();
@@ -1241,19 +1241,19 @@
$text = Article::getRevisionText( $old );
$blanked = true;
}
-
+
}
-
- $length=strlen($text);
-
+
+ $length=strlen($text);
+
# this should not happen, since it is not possible to store an empty, new
# page. Let's insert a standard text in case it does, though
- if($length == 0 && $reason === '') {
+ if($length == 0 && $reason === '') {
$reason = wfMsg('exblank');
}
-
+
if($length < 500 && $reason === '') {
-
+
# comment field=255, let's grep the first 150 to have some user
# space left
$text=substr($text,0,150);
@@ -1268,27 +1268,27 @@
$reason=wfMsg('exbeforeblank') . " '".$text;
}
if($length>150) { $reason .= '...'; } # we've only pasted part of the
text
- $reason.="'";
+ $reason.="'";
}
}
return $this->confirmDelete( '', $reason );
}
-
+
# Output deletion confirmation dialog
function confirmDelete( $par, $reason )
{
global $wgOut;
wfDebug( "Article::confirmDelete\n" );
-
+
$sub = htmlspecialchars( $this->mTitle->getPrefixedText() );
$wgOut->setSubtitle( wfMsg( 'deletesub', $sub ) );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$wgOut->addWikiText( wfMsg( 'confirmdeletetext' ) );
$formaction = $this->mTitle->escapeLocalURL( 'action=delete' . $par );
-
+
$confirm = htmlspecialchars( wfMsg( 'confirm' ) );
$check = htmlspecialchars( wfMsg( 'confirmcheck' ) );
$delcom = htmlspecialchars( wfMsg( 'deletecomment' ) );
@@ -1334,7 +1334,7 @@
$fname = 'Article::doDelete';
wfDebug( "$fname\n" );
- if ( $this->doDeleteArticle( $reason ) ) {
+ if ( $this->doDeleteArticle( $reason ) ) {
$deleted = $this->mTitle->getPrefixedText();
$wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
@@ -1375,14 +1375,14 @@
$u = new SiteStatsUpdate( 0, 1, -$this->isCountable( $this->getContent( true ) )
);
array_push( $wgDeferredUpdateList, $u );
-
+
$linksTo = $this->mTitle->getLinksTo();
# Squid purging
if ( $wgUseSquid ) {
- $urls = array(
+ $urls = array(
$this->mTitle->getInternalURL(),
- $this->mTitle->getInternalURL( 'history' )
+ $this->mTitle->getInternalURL( 'history' )
);
foreach ( $linksTo as $linkTo ) {
$urls[] = $linkTo->getInternalURL();
@@ -1420,7 +1420,7 @@
$sql = "DELETE FROM old WHERE old_namespace={$ns} AND " .
"old_title='{$t}'";
wfQuery( $sql, DB_WRITE, $fname );
-
+
$sql = "DELETE FROM recentchanges WHERE rc_namespace={$ns} AND " .
"rc_title='{$t}'";
wfQuery( $sql, DB_WRITE, $fname );
@@ -1429,7 +1429,7 @@
$t = wfStrencode( $this->mTitle->getPrefixedDBkey() );
Article::onArticleDelete( $this->mTitle );
-
+
$sql = 'INSERT INTO brokenlinks (bl_from,bl_to) VALUES ';
$first = true;
@@ -1437,7 +1437,7 @@
if ( ! $first ) { $sql .= ','; }
$first = false;
# Get article ID. Efficient because it was loaded into the cache by getLinksTo().
- $linkID = $titleObj->getArticleID();
+ $linkID = $titleObj->getArticleID();
$sql .= "({$linkID},'{$t}')";
}
if ( ! $first ) {
@@ -1455,10 +1455,10 @@
$sql = "DELETE FROM brokenlinks WHERE bl_from={$id}";
wfQuery( $sql, DB_WRITE, $fname );
-
+
$sql = "DELETE FROM categorylinks WHERE cl_from={$id}";
wfQuery( $sql, DB_WRITE, $fname );
-
+
$log = new LogPage( wfMsg( 'dellogpage' ), wfMsg( 'dellogpagetext' )
);
$art = $this->mTitle->getPrefixedText();
$log->addEntry( wfMsg( 'deletedarticle', $art ), $reason );
@@ -1481,14 +1481,14 @@
$wgOut->readOnlyPage( $this->getContent( true ) );
return;
}
-
+
# Enhanced rollback, marks edits rc_bot=1
$bot = $wgRequest->getBool( 'bot' );
-
+
# Replace all this user's current edits with the next one down
$tt = wfStrencode( $this->mTitle->getDBKey() );
$n = $this->mTitle->getNamespace();
-
+
# Get the last editor
$sql = 'SELECT cur_id,cur_user,cur_user_text,cur_comment ' .
"FROM cur WHERE cur_title='{$tt}' AND cur_namespace={$n}";
@@ -1502,7 +1502,7 @@
$ut = wfStrencode( $s->cur_user_text );
$uid = $s->cur_user;
$pid = $s->cur_id;
-
+
$from = str_replace( '_', ' ', $wgRequest->getVal( 'from' )
);
if( $from != $s->cur_user_text ) {
$wgOut->setPageTitle(wfmsg('rollbackfailed'));
@@ -1517,7 +1517,7 @@
}
return;
}
-
+
# Get the last edit not by this guy
$use_index=$wgIsMySQL?"USE INDEX (name_title_timestamp)":"";
@@ -1535,7 +1535,7 @@
return;
}
$s = wfFetchObject( $res );
-
+
if ( $bot ) {
# Mark all reverted edits as bot
$sql = 'UPDATE recentchanges SET rc_bot=1 WHERE ' .
@@ -1552,7 +1552,7 @@
Article::onArticleEdit( $this->mTitle );
$wgOut->returnToMain( false );
}
-
+
# Do standard deferred updates after page view
@@ -1589,7 +1589,7 @@
$id = $this->getID();
$title = $this->mTitle->getPrefixedDBkey();
$shortTitle = $this->mTitle->getDBkey();
-
+
$adj = $this->mCountAdjustment;
if ( 0 != $id ) {
@@ -1626,7 +1626,7 @@
global $wgParser, $wgUser;
return $wgParser->preSaveTransform( $text, $this->mTitle, $wgUser,
ParserOptions::newFromUser( $wgUser ) );
}
-
+
/* Caching functions */
# checkLastModified returns true if it has taken care of all
@@ -1653,7 +1653,7 @@
$cache->loadFromFileCache();
return true;
} else {
- wfDebug( " tryFileCache() - starting buffer\n" );
+ wfDebug( " tryFileCache() - starting buffer\n" );
ob_start( array(&$cache, 'saveToFileCache' ) );
}
} else {
@@ -1664,7 +1664,7 @@
function isFileCacheable() {
global $wgUser, $wgUseFileCache, $wgShowIPinHeader, $wgRequest;
extract( $wgRequest->getValues( 'action', 'oldid', 'diff',
'redirect', 'printable' ) );
-
+
return $wgUseFileCache
and (!$wgShowIPinHeader)
and ($this->getID() != 0)
@@ -1678,7 +1678,7 @@
and (!isset($printable))
and (!$this->mRedirectedFrom);
}
-
+
# Loads cur_touched and returns a value indicating if it should be used
function checkTouched() {
$id = $this->getID();
@@ -1702,14 +1702,14 @@
$dbkey = $this->mTitle->getDBkey();
$encDbKey = wfStrencode( $dbkey );
$timestamp = wfTimestampNow();
-
+
# Save to history
$oldtable=$wgIsPg?'"old"':'old';
$sql = "INSERT INTO $oldtable
(old_namespace,old_title,old_text,old_comment,old_user,old_user_text,old_timestamp,inverse_timestamp)
SELECT
cur_namespace,cur_title,cur_text,cur_comment,cur_user,cur_user_text,cur_timestamp,99999999999999-cur_timestamp
FROM cur WHERE cur_namespace=$ns AND cur_title='$encDbKey'";
wfQuery( $sql, DB_WRITE );
-
+
# Use the affected row count to determine if the article is new
$numRows = wfAffectedRows();
@@ -1746,14 +1746,14 @@
$id = intval( $id );
global $wgHitcounterUpdateFreq;
- if( $wgHitcounterUpdateFreq <= 1 ){ //
+ if( $wgHitcounterUpdateFreq <= 1 ){ //
wfQuery('UPDATE cur SET cur_counter = cur_counter + 1 ' .
'WHERE cur_id = '.$id, DB_WRITE);
return;
}
# Not important enough to warrant an error page in case of failure
- $oldignore = wfIgnoreSQLErrors( true );
+ $oldignore = wfIgnoreSQLErrors( true );
wfQuery("INSERT INTO hitcounter (hc_id) VALUES ({$id})", DB_WRITE);
@@ -1767,7 +1767,7 @@
$res = wfQuery('SELECT COUNT(*) as n FROM hitcounter', DB_WRITE);
$row = wfFetchObject( $res );
$rown = intval( $row->n );
- if( $rown >= $wgHitcounterUpdateFreq ){
+ if( $rown >= $wgHitcounterUpdateFreq ){
wfProfileIn( 'Article::incViewCount-collect' );
$old_user_abort = ignore_user_abort( true );
@@ -1788,18 +1788,18 @@
}
# The onArticle*() functions are supposed to be a kind of hooks
- # which should be called whenever any of the specified actions
- # are done.
+ # which should be called whenever any of the specified actions
+ # are done.
#
- # This is a good place to put code to clear caches, for instance.
+ # This is a good place to put code to clear caches, for instance.
- # This is called on page move and undelete, as well as edit
+ # This is called on page move and undelete, as well as edit
/* static */ function onArticleCreate($title_obj){
global $wgUseSquid, $wgDeferredUpdateList;
$titles = $title_obj->getBrokenLinksTo();
-
- # Purge squid
+
+ # Purge squid
if ( $wgUseSquid ) {
$urls = $title_obj->getSquidURLs();
foreach ( $titles as $linkTitle ) {
@@ -1820,6 +1820,90 @@
/* static */ function onArticleEdit($title_obj){
LinkCache::linksccClearPage( $title_obj->getArticleID() );
}
+
+ # Info about this page
+
+ function info()
+ {
+ global $wgUser, $wgTitle, $wgOut, $wgLang;
+
+ $basenamespace = $wgTitle->getNamespace() & (~1);
+ $cur_clause = "cur_title='".$wgTitle->getDBkey()."' AND
cur_namespace=".$basenamespace;
+ $old_clause = "old_title='".$wgTitle->getDBkey()."' AND
old_namespace=".$basenamespace;
+ $wl_clause = "wl_title='".$wgTitle->getDBkey()."' AND
wl_namespace=".$basenamespace;
+ $fullTitle = $wgTitle->makeName($basenamespace, $wgTitle->getDBKey());
+ $wgOut->setPagetitle( $fullTitle );
+ $wgOut->setSubtitle( wfMsg( "infosubtitle" ));
+
+ # first, see if the page exists at all.
+ $sql = "SELECT COUNT(*) FROM cur WHERE ".$cur_clause;
+ $exists = wfSingleQuery( $sql , DB_READ );
+ if ($exists < 1) {
+ $wgOut->addHTML( wfMsg("noarticletext") );
+ } else {
+ $sql = "SELECT COUNT(*) FROM watchlist WHERE ".$wl_clause;
+ $wgOut->addHTML( "<ul><li>" . wfMsg("numwatchers")
. wfSingleQuery( $sql, DB_READ ) . "</li>" );
+ $sql = "SELECT COUNT(*) FROM old WHERE ".$old_clause;
+ $old = wfSingleQuery( $sql, DB_READ );
+ $wgOut->addHTML( "<li>" . wfMsg("numedits") . ($old + 1)
. "</li>");
+
+ # to find number of distinct authors, we need to do some
+ # funny stuff because of the cur/old table split:
+ # - first, find the name of the 'cur' author
+ # - then, find the number of authors in 'old'
+ # - then, find out if the 'cur' author is anywhere in 'old'; if not,
add 1
+
+ # find 'cur' author
+ $sql = "SELECT cur_user_text FROM cur WHERE ".$cur_clause;
+ $cur_author = wfSingleQuery( $sql, DB_READ );
+
+ # find number of 'old' authors
+ $sql = "SELECT COUNT(DISTINCT old_user_text) FROM old WHERE ".$old_clause;
+ $authors = wfSingleQuery( $sql, DB_READ );
+
+ # find out if 'cur' author occurs in 'old'
+ $sql = "SELECT old_user_text FROM old WHERE ".$old_clause
+ ." AND old_user_text='".$cur_author."' LIMIT 1";
+ $res = wfQuery( $sql, DB_READ);
+ $has_cur_user = wfNumRows( $res );
+ wfFreeResult($res);
+ if ($has_cur_user < 1) { $authors++; }
+
+ # now for the Talk page ...
+ $cur_clause = "cur_title='".$wgTitle->getDBkey()."' AND
cur_namespace=".($basenamespace+1);
+ $old_clause = "old_title='".$wgTitle->getDBkey()."' AND
old_namespace=".($basenamespace+1);
+
+ # does it exist?
+ $sql = "SELECT COUNT(*) FROM cur WHERE ".$cur_clause;
+ $exists = wfSingleQuery( $sql , DB_READ );
+
+ # number of edits
+ if ($exists > 0) {
+ $sql = "SELECT COUNT(*) FROM old WHERE ".$old_clause;
+ $old = wfSingleQuery( $sql, DB_READ );
+ $wgOut->addHTML( "<li>" . wfMsg("numtalkedits") . ($old
+ 1) . "</li>");
+ }
+ $wgOut->addHTML( "<li>" . wfMsg("numauthors") . $authors
. "</li>" );
+
+ # number of authors
+ if ($exists > 0) {
+ $sql = "SELECT cur_user_text FROM cur WHERE ".$cur_clause;
+ $cur_author = wfSingleQuery( $sql, DB_READ );
+
+ $sql = "SELECT COUNT(DISTINCT old_user_text) FROM old WHERE ".$old_clause;
+ $authors = wfSingleQuery( $sql, DB_READ );
+
+ $sql = "SELECT old_user_text FROM old WHERE ".$old_clause
+ ." AND old_user_text='".$cur_author."' LIMIT 1";
+ $res = wfQuery( $sql, DB_READ);
+ $has_cur_user = wfNumRows( $res );
+ wfFreeResult($res);
+ if ($has_cur_user < 1) { $authors++; }
+
+ $wgOut->addHTML( "<li>" . wfMsg("numtalkauthors") .
$authors . "</li></ul>" );
+ }
+ }
+ }
}
?>
Index: includes/DatabaseFunctions.php
===================================================================
RCS file: /cvsroot/wikipedia/phase3/includes/DatabaseFunctions.php,v
retrieving revision 1.36
diff -u -r1.36 DatabaseFunctions.php
--- includes/DatabaseFunctions.php 22 Jun 2004 08:54:26 -0000 1.36
+++ includes/DatabaseFunctions.php 8 Jul 2004 11:04:20 -0000
@@ -39,6 +39,15 @@
}
}
+function wfSingleQuery( $sql, $db, $fname = "" )
+{
+ $res = wfQuery($sql, $db, $fname );
+ $row = wfFetchRow( $res );
+ $ret = $row[0];
+ wfFreeResult( $res );
+ return $ret;
+}
+
function &wfGetDB( $db = DB_LAST )
{
global $wgLoadBalancer;
Index: languages/Language.php
===================================================================
RCS file: /cvsroot/wikipedia/phase3/languages/Language.php,v
retrieving revision 1.257
diff -u -r1.257 Language.php
--- languages/Language.php 5 Jul 2004 21:26:35 -0000 1.257
+++ languages/Language.php 8 Jul 2004 11:04:20 -0000
@@ -1307,6 +1307,14 @@
'categoryarticlecount' => "There are $1 articles in this
category.",
'usenewcategorypage' => "1\n\nSet first character to \"0\" to
disable the new category page layout.",
+# Info page
+"infosubtitle" => "Information for page",
+"numedits" => "Number of edits (article): ",
+"numtalkedits" => "Number of edits (discussion page): ",
+"numwatchers" => "Number of watchers: ",
+"numauthors" => "Number of distinct authors (article): ",
+"numtalkauthors" => "Number of distinct authors (discussion page):
",
+
# Monobook.js: tooltips and access keys for monobook
'Monobook.js' => '/* tooltips and access keys */
ta = new Object();