MediaWiki r4919 - Code Review

Jump to: navigation, search
Repository:MediaWiki
Revision:r4918‎ | r4919 (on ViewVC)‎ | r4920 >
Date:08:11, 24 August 2004
Author:vibber
Status:old
Tags:
Comment:
Special:Log and the logging table -- unified logging scariness!

Replaces the ugly, often breaking, manually archived log pages with
a nice clean table which can be sorted, trimmed, viewed in pieces, etc.
You can see all logged actions by some user, or affecting some page,
and can combine the views of all all logs in one.

There are probably still some broken things in here, but I want this
committed before the patch gets any bigger.

recentchanges table is altered to make rc_namespace signed so Special:
links can be listed in it.
Modified paths:

Diff [purge]

Index: trunk/phase3/maintenance/archives/patch-logging.sql
@@ -0,0 +1,32 @@
 2+-- Add the logging table and adjust recentchanges to accomodate special pages
 3+-- 2004-08-24
 4+
 5+CREATE TABLE logging (
 6+ -- Symbolic keys for the general log type and the action type
 7+ -- within the log. The output format will be controlled by the
 8+ -- action field, but only the type controls categorization.
 9+ log_type char(10) NOT NULL default '',
 10+ log_action char(10) NOT NULL default '',
 11+
 12+ -- Timestamp. Duh.
 13+ log_timestamp char(14) NOT NULL default '19700101000000',
 14+
 15+ -- The user who performed this action; key to user_id
 16+ log_user int unsigned NOT NULL default 0,
 17+
 18+ -- Key to the page affected. Where a user is the target,
 19+ -- this will point to the user page.
 20+ log_namespace tinyint unsigned NOT NULL default 0,
 21+ log_title varchar(255) NOT NULL default '',
 22+
 23+ -- Freeform text. Interpreted as edit history comments.
 24+ log_comment varchar(255) NOT NULL default '',
 25+
 26+ KEY type_time (log_type, log_timestamp),
 27+ KEY user_time (log_user, log_timestamp),
 28+ KEY page_time (log_namespace, log_title, log_timestamp)
 29+);
 30+
 31+-- Change from unsigned to signed so we can store special pages
 32+ALTER TABLE recentchanges
 33+ MODIFY rc_namespace tinyint(3) NOT NULL default '0';
Property changes on: trunk/phase3/maintenance/archives/patch-logging.sql
___________________________________________________________________
Name: svn:eol-style
134 + native
Name: svn:keywords
235 + Author Date Id Revision
Index: trunk/phase3/maintenance/updaters.inc
@@ -205,4 +205,16 @@
206206 echo "ok\n";
207207 }
208208 }
 209+
 210+function do_logging_update() {
 211+ global $wgDatabase;
 212+ if ( $wgDatabase->tableExists( 'logging' ) ) {
 213+ echo "...logging table already unique.\n";
 214+ } else {
 215+ echo "Creating logging table and adjusting recentchanges... ";
 216+ dbsource( "maintenance/archives/patch-logging.sql", $wgDatabase );
 217+ echo "ok\n";
 218+ }
 219+}
 220+
209221 ?>
Index: trunk/phase3/maintenance/tables.sql
@@ -180,7 +180,7 @@
181181 rc_cur_time varchar(14) binary NOT NULL default '',
182182 rc_user int(10) unsigned NOT NULL default '0',
183183 rc_user_text varchar(255) binary NOT NULL default '',
184 - rc_namespace tinyint(3) unsigned NOT NULL default '0',
 184+ rc_namespace tinyint(3) NOT NULL default '0',
185185 rc_title varchar(255) binary NOT NULL default '',
186186 rc_comment varchar(255) binary NOT NULL default '',
187187 rc_minor tinyint(3) unsigned NOT NULL default '0',
@@ -265,4 +265,31 @@
266266 `val_value` int(11) default '0',
267267 `val_comment` varchar(255) NOT NULL default '',
268268 KEY `val_user` (`val_user`,`val_title`,`val_timestamp`)
269 -) TYPE=MyISAM;
 269+);
 270+
 271+
 272+CREATE TABLE logging (
 273+ -- Symbolic keys for the general log type and the action type
 274+ -- within the log. The output format will be controlled by the
 275+ -- action field, but only the type controls categorization.
 276+ log_type char(10) NOT NULL default '',
 277+ log_action char(10) NOT NULL default '',
 278+
 279+ -- Timestamp. Duh.
 280+ log_timestamp char(14) NOT NULL default '19700101000000',
 281+
 282+ -- The user who performed this action; key to user_id
 283+ log_user int unsigned NOT NULL default 0,
 284+
 285+ -- Key to the page affected. Where a user is the target,
 286+ -- this will point to the user page.
 287+ log_namespace tinyint unsigned NOT NULL default 0,
 288+ log_title varchar(255) NOT NULL default '',
 289+
 290+ -- Freeform text. Interpreted as edit history comments.
 291+ log_comment varchar(255) NOT NULL default '',
 292+
 293+ KEY type_time (log_type, log_timestamp),
 294+ KEY user_time (log_user, log_timestamp),
 295+ KEY page_time (log_namespace, log_title, log_timestamp)
 296+);
Index: trunk/phase3/config/index.php
@@ -478,6 +478,7 @@
479479 do_objectcache_update(); flush();
480480 do_categorylinks_update(); flush();
481481 do_image_name_unique_update(); flush();
 482+ do_logging_update(); flush();
482483
483484 if ( isTemplateInitialised() ) {
484485 print "Template namespace already initialised\n";
Index: trunk/phase3/includes/SpecialUndelete.php
@@ -247,8 +247,8 @@
248248
249249
250250 # Touch the log?
251 - $log = new LogPage( wfMsg( "dellogpage" ), wfMsg( "dellogpagetext" ) );
252 - $log->addEntry( wfMsg( "undeletedarticle", $this->mTarget ), "" );
 251+ $log = new LogPage( 'delete' );
 252+ $log->addEntry( 'restore', Title::makeTitle( $namespace, $title ), "" );
253253
254254 $wgOut->addWikiText( wfMsg( "undeletedtext", $this->mTarget ) );
255255 return 0;
Index: trunk/phase3/includes/SpecialIpblocklist.php
@@ -96,9 +96,8 @@
9797 $block->delete();
9898
9999 # Make log entry
100 - $log = new LogPage( wfMsg( "blocklogpage" ), wfMsg( "blocklogtext" ) );
101 - $action = wfMsg( "unblocklogentry", $this->ip );
102 - $log->addEntry( $action, $this->reason );
 100+ $log = new LogPage( 'block' );
 101+ $log->addEntry( 'unblock', Title::makeTitle( NS_USER, $this->ip ), $this->reason );
103102
104103 # Report to the user
105104 $titleObj = Title::makeTitle( NS_SPECIAL, "Ipblocklist" );
Index: trunk/phase3/includes/Image.php
@@ -443,11 +443,8 @@
444444 $descTitle->invalidateCache();
445445 }
446446
447 - $log = new LogPage( wfMsg( 'uploadlogpage' ), wfMsg( 'uploadlogpagetext' ) );
448 - $da = wfMsg( 'uploadedimage', '[[:' . $wgLang->getNsText(
449 - Namespace::getImage() ) . ":{$name}|{$name}]]" );
450 - $ta = wfMsg( 'uploadedimage', $name );
451 - $log->addEntry( $da, $desc, $ta );
 447+ $log = new LogPage( 'upload' );
 448+ $log->addEntry( 'upload', $descTitle, $desc );
452449 }
453450
454451 function wfImageArchiveUrl( $name )
Index: trunk/phase3/includes/SpecialLog.php
@@ -0,0 +1,267 @@
 2+<?php
 3+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
 4+# http://www.mediawiki.org/
 5+#
 6+# This program is free software; you can redistribute it and/or modify
 7+# it under the terms of the GNU General Public License as published by
 8+# the Free Software Foundation; either version 2 of the License, or
 9+# (at your option) any later version.
 10+#
 11+# This program is distributed in the hope that it will be useful,
 12+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 13+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 14+# GNU General Public License for more details.
 15+#
 16+# You should have received a copy of the GNU General Public License along
 17+# with this program; if not, write to the Free Software Foundation, Inc.,
 18+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 19+# http://www.gnu.org/copyleft/gpl.html
 20+
 21+function wfSpecialLog( $par = '' ) {
 22+ global $wgRequest;
 23+ $logReader =& new LogReader( $wgRequest );
 24+ if( '' == $wgRequest->getVal( 'type' ) && !empty( $par ) ) {
 25+ $logReader->limitType( $par );
 26+ }
 27+ $logViewer =& new LogViewer( $logReader );
 28+ $logViewer->show();
 29+ $logReader->cleanUp();
 30+}
 31+
 32+class LogReader {
 33+ var $db, $joinClauses, $whereClauses;
 34+ var $type = '', $user = '', $title = null;
 35+
 36+ function LogReader( $request ) {
 37+ $this->db =& wfGetDB( DB_SLAVE );
 38+ $this->setupQuery( $request );
 39+ }
 40+
 41+ function setupQuery( $request ) {
 42+ $cur = $this->db->tableName( 'cur' );
 43+ $user = $this->db->tableName( 'user' );
 44+ $this->joinClauses = array( "LEFT OUTER JOIN $cur ON log_namespace=cur_namespace AND log_title=cur_title" );
 45+ $this->whereClauses = array( 'user_id=log_user' );
 46+
 47+ $this->limitType( $request->getVal( 'type' ) );
 48+ $this->limitUser( $request->getText( 'user' ) );
 49+ $this->limitTitle( $request->getText( 'page' ) );
 50+ $this->limitTime( $request->getVal( 'from' ), '>=' );
 51+ $this->limitTime( $request->getVal( 'until' ), '<=' );
 52+
 53+ list( $this->limit, $this->offset ) = $request->getLimitOffset();
 54+ }
 55+
 56+ function limitType( $type ) {
 57+ if( empty( $type ) ) {
 58+ return false;
 59+ }
 60+ $this->type = $type;
 61+ $safetype = $this->db->strencode( $type );
 62+ $this->whereClauses[] = "log_type='$safetype'";
 63+ }
 64+
 65+ function limitUser( $name ) {
 66+ $title = Title::makeTitleSafe( NS_USER, $name );
 67+ if( empty( $name ) || is_null( $title ) ) {
 68+ return false;
 69+ }
 70+ $this->user = str_replace( '_', ' ', $title->getDBkey() );
 71+ $safename = $this->db->strencode( $this->user );
 72+ $user = $this->db->tableName( 'user' );
 73+ $this->whereClauses[] = "user_name='$safename'";
 74+ }
 75+
 76+ function limitTitle( $page ) {
 77+ $title = Title::newFromText( $page );
 78+ if( empty( $page ) || is_null( $title ) ) {
 79+ return false;
 80+ }
 81+ $this->title =& $title;
 82+ $safetitle = $this->db->strencode( $title->getDBkey() );
 83+ $ns = $title->getNamespace();
 84+ $this->whereClauses[] = "log_namespace=$ns AND log_title='$safetitle'";
 85+ }
 86+
 87+ function limitTime( $time, $direction ) {
 88+ # Direction should be a comparison operator
 89+ if( empty( $time ) ) {
 90+ return false;
 91+ }
 92+ $safetime = $this->db->strencode( wfTimestamp( TS_MW, $time ) );
 93+ $this->whereClauses[] = "log_timestamp $direction '$safetime'";
 94+ }
 95+
 96+ function getQuery() {
 97+ $logging = $this->db->tableName( "logging" );
 98+ $user = $this->db->tableName( 'user' );
 99+ $sql = "SELECT log_type, log_action, log_timestamp,
 100+ log_user, user_name,
 101+ log_namespace, log_title, cur_id,
 102+ log_comment FROM $logging, $user ";
 103+ if( !empty( $this->joinClauses ) ) {
 104+ $sql .= implode( ',', $this->joinClauses );
 105+ }
 106+ if( !empty( $this->whereClauses ) ) {
 107+ $sql .= " WHERE " . implode( ' AND ', $this->whereClauses );
 108+ }
 109+ $sql .= " ORDER BY log_timestamp DESC ";
 110+ $sql .= $this->db->limitResult( $this->limit, $this->offset );
 111+ return $sql;
 112+ }
 113+
 114+ function initQuery() {
 115+ $this->result = $this->db->query( $this->getQuery() );
 116+ }
 117+
 118+ function fetchObject() {
 119+ return $this->db->fetchObject( $this->result );
 120+ }
 121+
 122+ function cleanUp() {
 123+ $this->db->freeResult( $this->result );
 124+ }
 125+
 126+ function queryType() {
 127+ return $this->type;
 128+ }
 129+
 130+ function queryUser() {
 131+ return $this->user;
 132+ }
 133+
 134+ function queryTitle() {
 135+ if( is_null( $this->title ) ) {
 136+ return '';
 137+ } else {
 138+ return $this->title->getPrefixedText();
 139+ }
 140+ }
 141+}
 142+
 143+class LogViewer {
 144+ var $reader, $skin;
 145+ var $typeText = array(
 146+ '' => array( 'log', 'alllogstext' ),
 147+ 'block' => array( 'blocklogpage', 'blocklogtext' ),
 148+ 'protect' => array( 'protectlogpage', 'protectlogtext' ),
 149+ 'rights' => array( 'bureaucratlog', '' ),
 150+ 'delete' => array( 'dellogpage', 'dellogpagetext' ),
 151+ 'upload' => array( 'uploadlogpage', 'uploadlogpagetext' )
 152+ );
 153+
 154+
 155+ function LogViewer( &$reader ) {
 156+ global $wgUser;
 157+ $this->skin =& $wgUser->getSkin();
 158+ $this->reader =& $reader;
 159+ }
 160+
 161+ function show() {
 162+ global $wgOut;
 163+ $this->showHeader( $wgOut );
 164+ $this->showOptions( $wgOut );
 165+ $this->showPrevNext( $wgOut );
 166+ $out = "";
 167+ $this->reader->initQuery();
 168+ while( $s = $this->reader->fetchObject() ) {
 169+ $out .= $this->logLine( $s );
 170+ }
 171+ $wgOut->addHTML( $out );
 172+ $this->showPrevNext( $wgOut );
 173+ }
 174+
 175+ # wfMsg( unprotectedarticle, $text )
 176+ # wfMsg( 'protectedarticle', $text )
 177+ # wfMsg( 'deletedarticle', $text )
 178+ # wfMsg( 'uploadedimage', $text )
 179+ # wfMsg( "blocklogentry", $this->BlockAddress, $this->BlockExpiry );
 180+ # wfMsg( "bureaucratlogentry", $this->mUser, implode( " ", $rightsNotation ) );
 181+ # wfMsg( "undeletedarticle", $this->mTarget ),
 182+ function logLine( $s ) {
 183+ global $wgLang;
 184+ $title = Title::makeTitle( $s->log_namespace, $s->log_title );
 185+ $user = Title::makeTitleSafe( NS_USER, $s->user_name );
 186+ $time = $wgLang->timeanddate( $s->log_timestamp );
 187+ if( $s->cur_id ) {
 188+ $titleLink = $this->skin->makeKnownLinkObj( $title );
 189+ } else {
 190+ $titleLink = $this->skin->makeBrokenLinkObj( $title );
 191+ }
 192+ $userLink = $this->skin->makeLinkObj( $user, htmlspecialchars( $s->user_name ) );
 193+ if( '' === $s->log_comment ) {
 194+ $comment = '';
 195+ } else {
 196+ $comment = '(<em>' . $this->skin->formatComment( $s->log_comment ) . '</em>)';
 197+ }
 198+
 199+ $action = LogPage::actionText( $s->log_type, $s->log_action, $titleLink );
 200+ $out = "<li>$time $userLink $action $comment</li>\n";
 201+ return $out;
 202+ }
 203+
 204+ function showHeader( &$out ) {
 205+ $type = $this->reader->queryType();
 206+ if( isset( $this->typeText[$type] ) ) {
 207+ list( $title, $headertext ) = $this->typeText[$type];
 208+ $out->setPageTitle( str_replace( '_', ' ', wfMsg( $title ) ) );
 209+ $out->addWikiText( wfMsg( $headertext ) );
 210+ }
 211+ }
 212+
 213+ function showOptions( &$out ) {
 214+ global $wgScript;
 215+ $action = htmlspecialchars( $wgScript );
 216+ $title = Title::makeTitle( NS_SPECIAL, 'Log' );
 217+ $special = htmlspecialchars( $title->getPrefixedDBkey() );
 218+ $out->addHTML( "<form action=\"$action\" method=\"get\">\n" .
 219+ "<input type='hidden' name='title' value=\"$special\" />\n" .
 220+ $this->getTypeMenu() .
 221+ $this->getUserInput() .
 222+ $this->getTitleInput() .
 223+ "<input type='submit' />" .
 224+ "</form>" );
 225+ }
 226+
 227+ function getTypeMenu() {
 228+ $out = "<select name='type'>\n";
 229+ foreach( $this->typeText as $type => $msg ) {
 230+ $text = htmlspecialchars( str_replace( '_', ' ', wfMsg( $msg[0] ) ) );
 231+ $selected = ($type == $this->reader->queryType()) ? ' selected="selected"' : '';
 232+ $out .= "<option value=\"$type\"$selected>$text</option>\n";
 233+ }
 234+ $out .= "</select>\n";
 235+ return $out;
 236+ }
 237+
 238+ function getUserInput() {
 239+ $user = htmlspecialchars( $this->reader->queryUser() );
 240+ return "User: <input type='text' name='user' size='12' value=\"$user\" />\n";
 241+ }
 242+
 243+ function getTitleInput() {
 244+ $title = htmlspecialchars( $this->reader->queryTitle() );
 245+ return "Title: <input type='text' name='page' size='20' value=\"$title\" />\n";
 246+ }
 247+
 248+ function showPrevNext( &$out ) {
 249+ global $wgLang;
 250+ $pieces = array();
 251+ $pieces[] = 'type=' . htmlspecialchars( $this->reader->queryType() );
 252+ $pieces[] = 'user=' . htmlspecialchars( $this->reader->queryUser() );
 253+ $pieces[] = 'page=' . htmlspecialchars( $this->reader->queryTitle() );
 254+ $bits = implode( '&', $pieces );
 255+ $offset = 0; $limit = 50;
 256+
 257+ # TODO: use timestamps instead of offsets to make it more natural
 258+ # to go huge distances in time
 259+ $html = wfViewPrevNext( $offset, $limit,
 260+ $wgLang->specialpage( 'Log' ),
 261+ $bits,
 262+ false);
 263+ $out->addHTML( '<p>' . $html . '</p>' );
 264+ }
 265+}
 266+
 267+
 268+?>
\ No newline at end of file
Property changes on: trunk/phase3/includes/SpecialLog.php
___________________________________________________________________
Name: svn:eol-style
1269 + native
Name: svn:keywords
2270 + Author Date Id Revision
Index: trunk/phase3/includes/Article.php
@@ -8,7 +8,6 @@
99 # moved to separate EditPage and CacheManager classes.
1010
1111 require_once ( 'CacheManager.php' );
12 -include_once ( 'SpecialValidate.php' ) ;
1312
1413 $wgArticleCurContentFields = false;
1514 $wgArticleOldContentFields = false;
@@ -1088,6 +1087,7 @@
10891088 function validate () {
10901089 global $wgOut, $wgUseValidation;
10911090 if( $wgUseValidation ) {
 1091+ require_once ( 'SpecialValidate.php' ) ;
10921092 $wgOut->setPagetitle( wfMsg( 'validate' ) . ': ' . $this->mTitle->getPrefixedText() );
10931093 $wgOut->setRobotpolicy( 'noindex,follow' );
10941094 if( $this->mTitle->getNamespace() != 0 ) {
@@ -1210,11 +1210,11 @@
12111211 ), 'Article::protect'
12121212 );
12131213
1214 - $log = new LogPage( wfMsg( 'protectlogpage' ), wfMsg( 'protectlogtext' ) );
 1214+ $log = new LogPage( 'protect' );
12151215 if ( $limit === '' ) {
1216 - $log->addEntry( wfMsg( 'unprotectedarticle', $this->mTitle->getPrefixedText() ), $reason );
 1216+ $log->addEntry( 'unprotect', $this->mTitle, $reason );
12171217 } else {
1218 - $log->addEntry( wfMsg( 'protectedarticle', $this->mTitle->getPrefixedText() ), $reason );
 1218+ $log->addEntry( 'protect', $this->mTitle, $reason );
12191219 }
12201220 $wgOut->redirect( $this->mTitle->getFullURL() );
12211221 return;
@@ -1592,9 +1592,8 @@
15931593 $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) );
15941594
15951595 # Log the deletion
1596 - $log = new LogPage( wfMsg( 'dellogpage' ), wfMsg( 'dellogpagetext' ) );
1597 - $art = $this->mTitle->getPrefixedText();
1598 - $log->addEntry( wfMsg( 'deletedarticle', $art ), $reason );
 1596+ $log = new LogPage( 'delete' );
 1597+ $log->addEntry( 'delete', $this->mTitle, $reason );
15991598
16001599 # Clear the cached article id so the interface doesn't act like we exist
16011600 $this->mTitle->resetArticleID( 0 );
Index: trunk/phase3/includes/SpecialMakesysop.php
@@ -194,12 +194,10 @@
195195 $dbw->query($sql);
196196 $wgMemc->delete( "$dbName:user:id:$id" );
197197
198 - $bureaucratLog = wfMsg( "bureaucratlog" );
199 - $action = wfMsg( "bureaucratlogentry", $this->mUser, implode( " ", $rightsNotation ) );
 198+ $log = new LogPage( 'rights' );
 199+ $log->addEntry( 'rights', Title::makeTitle( NS_USER, $this->mUser ),
 200+ implode( " ", $rightsNotation ) );
200201
201 - $log = new LogPage( $bureaucratLog );
202 - $log->addEntry( $action, "" );
203 -
204202 $this->showSuccess();
205203 }
206204 }
Index: trunk/phase3/includes/SpecialPage.php
@@ -62,6 +62,7 @@
6363 "Version" => new SpecialPage( "Version" ),
6464 "Allmessages" => new SpecialPage( "Allmessages" ),
6565 "Search" => new UnlistedSpecialPage( "Search" ),
 66+ "Log" => new SpecialPage( "Log" ),
6667 "Blockip" => new SpecialPage( "Blockip", "sysop" ),
6768 "Asksql" => new SpecialPage( "Asksql", "sysop" ),
6869 "Undelete" => new SpecialPage( "Undelete", "sysop" ),
Index: trunk/phase3/includes/LogPage.php
@@ -1,58 +1,38 @@
22 <?php
33 #$Id$
44 #
5 -# Class to simplify the use of log pages
 5+# Copyright (C) 2002, 2004 Brion Vibber <brion@pobox.com>
 6+# http://www.mediawiki.org/
 7+#
 8+# This program is free software; you can redistribute it and/or modify
 9+# it under the terms of the GNU General Public License as published by
 10+# the Free Software Foundation; either version 2 of the License, or
 11+# (at your option) any later version.
 12+#
 13+# This program is distributed in the hope that it will be useful,
 14+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+# GNU General Public License for more details.
 17+#
 18+# You should have received a copy of the GNU General Public License along
 19+# with this program; if not, write to the Free Software Foundation, Inc.,
 20+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 21+# http://www.gnu.org/copyleft/gpl.html
622
 23+# Class to simplify the use of log pages.
 24+# The logs are now kept in a table which is easier to manage and trim
 25+# than ever-growing wiki pages.
 26+
727 class LogPage {
8 - /* private */ var $mTitle, $mContent, $mContentLoaded, $mId, $mComment;
9 - var $mUpdateRecentChanges ;
 28+ /* private */ var $type, $action, $comment;
 29+ var $updateRecentChanges = true;
1030
11 - function LogPage( $title, $defaulttext = "<ul>\n</ul>" )
12 - {
13 - # For now, assume title is correct dbkey
14 - # and log pages always go in Wikipedia namespace
15 - $this->mTitle = str_replace( ' ', '_', $title );
16 - $this->mId = 0;
17 - $this->mUpdateRecentChanges = true ;
18 - $this->mContentLoaded = false;
19 - $this->getContent( $defaulttext );
 31+ function LogPage( $type ) {
 32+ # Type is one of 'block', 'protect', 'rights', 'delete', 'upload'
 33+ $this->type = $type;
2034 }
2135
22 - function getContent( $defaulttext = "<ul>\n</ul>" )
23 - {
24 - $fname = 'LogPage::getContent';
25 -
26 - $dbw =& wfGetDB( DB_MASTER );
27 - $s = $dbw->getArray( 'cur',
28 - array( 'cur_id','cur_text','cur_timestamp' ),
29 - array( 'cur_namespace' => Namespace::getWikipedia(), 'cur_title' => $this->mTitle ),
30 - $fname, 'FOR UPDATE'
31 - );
32 -
33 - if( $s !== false ) {
34 - $this->mId = $s->cur_id;
35 - $this->mContent = $s->cur_text;
36 - $this->mTimestamp = wfTimestamp(TS_MW,$s->cur_timestamp);
37 - } else {
38 - $this->mId = 0;
39 - $this->mContent = $defaulttext;
40 - $this->mTimestamp = wfTimestamp(TS_MW);
41 - }
42 - $this->mContentLoaded = true; # Well, sort of
43 -
44 - return $this->mContent;
45 - }
46 -
47 - function getTimestamp()
48 - {
49 - if( !$this->mContentLoaded ) {
50 - $this->getContent();
51 - }
52 - return $this->mTimestamp;
53 - }
54 -
55 - function saveContent()
56 - {
 36+ function saveContent() {
5737 if( wfReadOnly() ) return;
5838
5939 global $wgUser;
@@ -61,128 +41,63 @@
6242 $dbw =& wfGetDB( DB_MASTER );
6343 $uid = $wgUser->getID();
6444
65 - if( !$this->mContentLoaded ) return false;
66 - $this->mTimestamp = $now = wfTimestampNow();
67 - $won = wfInvertTimestamp( $now );
68 - if($this->mId == 0) {
69 - $seqVal = $dbw->nextSequenceValue( 'cur_cur_id_seq' );
70 -
71 - # Note: this query will deadlock if another thread has called getContent(),
72 - # at least in MySQL 4.0.17 InnoDB
73 - $dbw->insertArray( 'cur',
74 - array(
75 - 'cur_id' => $seqVal,
76 - 'cur_timestamp' => $dbw->timestamp($now),
77 - 'cur_user' => $uid,
78 - 'cur_user_text' => $wgUser->getName(),
79 - 'cur_namespace' => NS_WIKIPEDIA,
80 - 'cur_title' => $this->mTitle,
81 - 'cur_text' => $this->mContent,
82 - 'cur_comment' => $this->mComment,
83 - 'cur_restrictions' => 'sysop',
84 - 'inverse_timestamp' => $won,
85 - 'cur_touched' => $dbw->timestamp($now),
86 - ), $fname
87 - );
88 - $this->mId = $dbw->insertId();
89 - } else {
90 - $dbw->updateArray( 'cur',
91 - array( /* SET */
92 - 'cur_timestamp' => $dbw->timestamp($now),
93 - 'cur_user' => $uid,
94 - 'cur_user_text' => $wgUser->getName(),
95 - 'cur_text' => $this->mContent,
96 - 'cur_comment' => $this->mComment,
97 - 'cur_restrictions' => 'sysop',
98 - 'inverse_timestamp' => $won,
99 - 'cur_touched' => $dbw->timestamp($now),
100 - ), array( /* WHERE */
101 - 'cur_id' => $this->mId
102 - ), $fname
103 - );
104 - }
 45+ $this->timestamp = $now = wfTimestampNow();
 46+ $dbw->insertArray( 'logging',
 47+ array(
 48+ 'log_type' => $this->type,
 49+ 'log_action' => $this->action,
 50+ 'log_timestamp' => $dbw->timestamp( $now ),
 51+ 'log_user' => $uid,
 52+ 'log_namespace' => $this->target->getNamespace(),
 53+ 'log_title' => $this->target->getDBkey(),
 54+ 'log_comment' => $this->comment
 55+ ), $fname
 56+ );
10557
10658 # And update recentchanges
107 - if ( $this->mUpdateRecentChanges ) {
108 - $titleObj = Title::makeTitle( Namespace::getWikipedia(), $this->mTitle );
109 - RecentChange::notifyLog( $now, $titleObj, $wgUser, $this->mComment );
 59+ if ( $this->updateRecentChanges ) {
 60+ $rcComment = $this->actionText;
 61+ if( '' != $this->comment ) {
 62+ $rcComment .= ': ' . $this->comment;
 63+ }
 64+ $titleObj = Title::makeTitle( NS_SPECIAL, 'Log/' . $this->type );
 65+ RecentChange::notifyLog( $now, $titleObj, $wgUser, $rcComment );
11066 }
11167 return true;
11268 }
11369
114 - function addEntry( $action, $comment, $textaction = '' )
115 - {
116 - global $wgLang, $wgUser;
117 -
118 - $comment_esc = wfEscapeWikiText( $comment );
119 -
120 - $this->getContent();
121 -
122 - $ut = $wgUser->getName();
123 - $uid = $wgUser->getID();
124 - if( $uid ) {
125 - $ul = '[[' .
126 - $wgLang->getNsText( Namespace::getUser() ) .
127 - ":{$ut}|{$ut}]]";
 70+ /* static */ function actionText( $type, $action, $titleLink ) {
 71+ static $actions = array(
 72+ 'block/block' => 'blocklogentry',
 73+ 'block/unblock' => 'blocklogentry',
 74+ 'protect/protect' => 'protectedarticle',
 75+ 'protect/unprotect' => 'unprotectedarticle',
 76+ 'rights/rights' => 'bureaucratlogentry',
 77+ 'delete/delete' => 'deletedarticle',
 78+ 'delete/restore' => 'undeletedarticle',
 79+ 'upload/upload' => 'uploadedimage',
 80+ 'upload/revert' => 'uploadedimage',
 81+ );
 82+ $key = "$type/$action";
 83+ if( isset( $actions[$key] ) ) {
 84+ return wfMsg( $actions[$key], $titleLink );
12885 } else {
129 - $ul = $ut;
 86+ wfDebug( "LogPage::actionText - unknown action $key\n" );
 87+ return "$action $titleLink";
13088 }
131 -
132 - # Use the wiki-wide default date format instead of the user's setting
133 - $d = $wgLang->timeanddate( wfTimestampNow(), false, MW_DATE_DEFAULT );
134 -
135 - if( preg_match( "/^(.*?)<ul>(.*)$/sD", $this->mContent, $m ) ) {
136 - $before = $m[1];
137 - $after = $m[2];
138 - } else {
139 - $before = '';
140 - $after = '';
141 - }
142 -
143 - if($textaction)
144 - $this->mComment = $textaction;
145 - else
146 - $this->mComment = $action;
147 -
148 - if ( '' == $comment ) {
149 - $inline = '';
150 - } else {
151 - $inline = " <em>({$comment_esc})</em>";
152 - # comment gets escaped again, so we use the unescaped version
153 - $this->mComment .= ': '.$comment;
154 - }
155 - $this->mContent = "{$before}<ul><li>{$d} {$ul} {$action}{$inline}</li>\n{$after}";
156 -
157 - # TODO: automatic log rotation...
158 -
159 - return $this->saveContent();
16089 }
16190
162 - function replaceContent( $text, $comment = '' )
163 - {
164 - $this->mContent = $text;
165 - $this->mComment = $comment;
166 - $this->mTimestamp = wfTimestampNow();
 91+ function addEntry( $action, &$target, $comment ) {
 92+ global $wgLang, $wgUser;
 93+
 94+ $this->action = $action;
 95+ $this->target =& $target;
 96+ $this->comment = $comment;
 97+ $this->actionText = LogPage::actionText( $this->type, $action,
 98+ $target->getPrefixedText() );
 99+
167100 return $this->saveContent();
168101 }
169 -
170 - function showAsDisabledPage( $rawhtml = true )
171 - {
172 - global $wgLang, $wgOut;
173 - if( $wgOut->checkLastModified( $this->getTimestamp() ) ){
174 - # Client cache fresh and headers sent, nothing more to do.
175 - return;
176 - }
177 - $func = ( $rawhtml ? 'addHTML' : 'addWikiText' );
178 - $wgOut->$func(
179 - "<p>" . wfMsg( 'perfdisabled' ) . "</p>\n\n" .
180 - "<p>" . wfMsg( 'perfdisabledsub', $wgLang->timeanddate( $this->getTimestamp() ) ) . "</p>\n\n" .
181 - "<hr />\n\n" .
182 - $this->getContent()
183 - );
184 - return;
185 -
186 - }
187102 }
188103
189104 ?>
Index: trunk/phase3/includes/SpecialBlockip.php
@@ -153,9 +153,8 @@
154154 $ban->insert();
155155
156156 # Make log entry
157 - $log = new LogPage( wfMsg( "blocklogpage" ), wfMsg( "blocklogtext" ) );
158 - $action = wfMsg( "blocklogentry", $this->BlockAddress, $this->BlockExpiry );
159 - $log->addEntry( $action, $this->BlockReason );
 157+ $log = new LogPage( 'block' );
 158+ $log->addEntry( 'block', Title::makeTitle( NS_USER, $this->BlockAddress ), $this->BlockReason );
160159
161160 # Report to the user
162161 $titleObj = Title::makeTitle( NS_SPECIAL, "Blockip" );
Index: trunk/phase3/RELEASE-NOTES
@@ -16,6 +16,7 @@
1717 * 'Recentchanges Patrol' to mark new edits that haven't yet been viewed
1818 * Support for faster C++ diff module (WikiDiff extension)
1919 * More scary link caching modes
 20+* Old manually maintained log pages replaced with searchable Special:Log
2021 * ... and more!
2122
2223 === Caveats ===
Index: trunk/phase3/languages/Language.php
@@ -1014,6 +1014,9 @@
10151015 'rfcurl' => "http://www.faqs.org/rfcs/rfc$1.html",
10161016 'alphaindexline' => "$1 to $2",
10171017 'version' => 'Version',
 1018+'log' => 'Logs',
 1019+'alllogstext' => 'Combined display of upload, deletion, protection, blocking, and sysop logs.
 1020+You can narrow down the view by selecting a log type, the user name, or the affected page.',
10181021
10191022 # Special:Allpages
10201023 'nextpage' => 'Next page ($1)',

Status & tagging log

  • 01:56, 13 October 2010 ^demon (talk | contribs) changed the status of r4919 [removed: new added: old]