Index: trunk/phase3/maintenance/archives/patch-change_tag.sql
===================================================================
--- trunk/phase3/maintenance/archives/patch-change_tag.sql (revision 0)
+++ trunk/phase3/maintenance/archives/patch-change_tag.sql (revision 46460)
@@ -0,0 +1,31 @@
+-- A table to track tags for revisions, logs and recent changes.
+-- Andrew Garrett, 2009-01
+CREATE TABLE /*_*/change_tag (
+ ct_rc_id int NULL,
+ ct_log_id int NULL,
+ ct_rev_id int NULL,
+ ct_tag varchar(255) NOT NULL,
+ ct_params BLOB NULL,
+
+ UNIQUE KEY (ct_rc_id,ct_tag),
+ UNIQUE KEY (ct_log_id,ct_tag),
+ UNIQUE KEY (ct_rev_id,ct_tag),
+ KEY (ct_tag,ct_rc_id,ct_rev_id,ct_log_id) -- Covering index, so we can pull all the info only out of the index.
+) /*$wgDBTableOptions*/;
+
+-- Rollup table to pull a LIST of tags simply without ugly GROUP_CONCAT that only works on MySQL 4.1+
+CREATE TABLE /*_*/tag_summary (
+ ts_rc_id int NULL,
+ ts_log_id int NULL,
+ ts_rev_id int NULL,
+ ts_tags BLOB NOT NULL,
+
+ UNIQUE KEY (ts_rc_id),
+ UNIQUE KEY (ts_log_id),
+ UNIQUE KEY (ts_rev_id)
+) /*$wgDBTableOptions*/;
+
+CREATE TABLE /*_*/valid_tag (
+ vt_tag varchar(255) NOT NULL,
+ PRIMARY KEY (vt_tag)
+) /*$wgDBTableOptions*/;
\ No newline at end of file
Index: trunk/phase3/maintenance/updaters.inc
===================================================================
--- trunk/phase3/maintenance/updaters.inc (revision 46459)
+++ trunk/phase3/maintenance/updaters.inc (revision 46460)
@@ -158,6 +158,9 @@
array( 'do_active_users_init' ),
array( 'add_field', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ),
array( 'sqlite_initial_indexes' ),
+ array( 'add_table', 'change_tag', 'patch-change_tag.sql' ),
+ array( 'add_table', 'tag_summary', 'patch-change_tag.sql' ),
+ array( 'add_table', 'valid_tag', 'patch-change_tag.sql' ),
),
);
Index: trunk/phase3/maintenance/tables.sql
===================================================================
--- trunk/phase3/maintenance/tables.sql (revision 46459)
+++ trunk/phase3/maintenance/tables.sql (revision 46460)
@@ -1234,4 +1234,36 @@
ul_key varchar(255) NOT NULL PRIMARY KEY
) /*$wgDBTableOptions*/;
+--- A table to track tags for revisions, logs and recent changes.
+REATE TABLE /*_*/change_tag (
+ ct_rc_id int NULL,
+ ct_log_id int NULL,
+ ct_rev_id int NULL,
+ ct_tag varchar(255) NOT NULL,
+ ct_params BLOB NULL,
+
+ UNIQUE KEY (ct_rc_id,ct_tag),
+ UNIQUE KEY (ct_log_id,ct_tag),
+ UNIQUE KEY (ct_rev_id,ct_tag),
+ KEY (ct_tag,ct_rc_id,ct_rev_id,ct_log_id) -- Covering index, so we can pull all the info only out of the index.
+) /*$wgDBTableOptions*/;
+
+-- Rollup table to pull a LIST of tags simply without ugly GROUP_CONCAT that only works on MySQL 4.1+
+CREATE TABLE /*_*/tag_summary (
+ ts_rc_id int NULL,
+ ts_log_id int NULL,
+ ts_rev_id int NULL,
+ ts_tags BLOB NOT NULL,
+
+ UNIQUE KEY (ts_rc_id),
+ UNIQUE KEY (ts_log_id),
+ UNIQUE KEY (ts_rev_id),
+) /*$wgDBTableOptions*/;
+
+CREATE TABLE /*_*/valid_tag (
+ vt_tag varchar(255) NOT NULL,
+ PRIMARY KEY (vt_tag)
+) /*$wgDBTableOptions*/;
+
+
-- vim: sw=2 sts=2 et
Index: trunk/phase3/skins/common/history.js
===================================================================
--- trunk/phase3/skins/common/history.js (revision 46459)
+++ trunk/phase3/skins/common/history.js (revision 46460)
@@ -27,7 +27,13 @@
}
if (oli) { // it's the second checked radio
if (inputs[1].checked) {
- oli.className = "selected";
+ if ( (typeof oli.className) != 'undefined') {
+ oli.classNameOriginal = oli.className.replace( 'selected', '' );
+ } else {
+ oli.classNameOriginal = '';
+ }
+
+ oli.className = "selected "+oli.classNameOriginal;
return false;
}
} else if (inputs[0].checked) {
@@ -42,7 +48,13 @@
if (dli) {
inputs[1].style.visibility = 'hidden';
}
- lis[i].className = "selected";
+ if ( (typeof lis[i].className) != 'undefined') {
+ lis[i].classNameOriginal = lis[i].className.replace( 'selected', '' );
+ } else {
+ lis[i].classNameOriginal = '';
+ }
+
+ lis[i].className = "selected "+lis[i].classNameOriginal;
oli = lis[i];
} else { // no radio is checked in this row
if (!oli) {
@@ -55,7 +67,7 @@
} else {
inputs[1].style.visibility = 'visible';
}
- lis[i].className = "";
+ lis[i].className = lis[i].classNameOriginal;
}
}
}
Index: trunk/phase3/docs/hooks.txt
===================================================================
--- trunk/phase3/docs/hooks.txt (revision 46459)
+++ trunk/phase3/docs/hooks.txt (revision 46460)
@@ -846,6 +846,9 @@
'LinksUpdateConstructed': At the end of LinksUpdate() is contruction.
&$linksUpdate: the LinkUpdate object
+'ListDefinedTags': When trying to find all defined tags.
+&$tags: The list of tags.
+
'LoadAllMessages': called by MessageCache::loadAllMessages() to load extensions messages
'LoadExtensionSchemaUpdates': called by maintenance/updaters.inc when upgrading database schema
Index: trunk/phase3/includes/ChangeTags.php
===================================================================
--- trunk/phase3/includes/ChangeTags.php (revision 0)
+++ trunk/phase3/includes/ChangeTags.php (revision 46460)
@@ -0,0 +1,163 @@
+<?php
+
+if (!defined( 'MEDIAWIKI' ))
+ die;
+
+class ChangeTags {
+ static function formatSummaryRow( $tags, $page ) {
+ if (!$tags)
+ return array('',array());
+
+ $classes = array();
+
+ $tags = explode( ',', $tags );
+ $displayTags = array();
+ foreach( $tags as $tag ) {
+ $displayTags[] = self::tagDescription( $tag );
+ $classes[] = "mw-tag-$tag";
+ }
+
+ return array( '(' . implode( ', ', $displayTags ) . ')', $classes );
+ }
+
+ static function tagDescription( $tag ) {
+ $msg = wfMsgExt( "tag-$tag", 'parseinline' );
+ if ( wfEmptyMsg( "tag-$tag", $msg ) ) {
+ return htmlspecialchars($tag);
+ }
+ return $msg;
+ }
+
+ ## Basic utility method to add tags to a particular change, given its rc_id, rev_id and/or log_id.
+ static function addTags( $tags, $rc_id=null, $rev_id=null, $log_id=null, $params = null ) {
+ if ( !is_array($tags) ) {
+ $tags = array( $tags );
+ }
+
+ $tags = array_filter( $tags ); // Make sure we're submitting all tags...
+
+ if (!$rc_id && !$rev_id && !$log_id) {
+ throw new MWException( "At least one of: RCID, revision ID, and log ID MUST be specified when adding a tag to a change!" );
+ }
+
+ $dbr = wfGetDB( DB_SLAVE );
+
+ // Might as well look for rcids and so on.
+ if (!$rc_id) {
+ $dbr = wfGetDB( DB_MASTER ); // Info might be out of date, somewhat fractionally, on slave.
+ if ($log_id) {
+ $rc_id = $dbr->selectField( 'recentchanges', 'rc_id', array( 'rc_logid' => $log_id ), __METHOD__ );
+ } elseif ($rev_id) {
+ $rc_id = $dbr->selectField( 'recentchanges', 'rc_id', array( 'rc_this_oldid' => $rev_id ), __METHOD__ );
+ }
+ } elseif (!$log_id && !$rev_id) {
+ $dbr = wfGetDB( DB_MASTER ); // Info might be out of date, somewhat fractionally, on slave.
+ $log_id = $dbr->selectField( 'recentchanges', 'rc_logid', array( 'rc_id' => $rc_id ), __METHOD__ );
+ $rev_id = $dbr->selectField( 'recentchanges', 'rc_this_oldid', array( 'rc_id' => $rc_id ), __METHOD__ );
+ }
+
+ $tsConds = array_filter( array( 'ts_rc_id' => $rc_id, 'ts_rev_id' => $rev_id, 'ts_log_id' => $log_id ) );
+
+ ## Update the summary row.
+ $prevTags = $dbr->selectField( 'tag_summary', 'ts_tags', $tsConds, __METHOD__ );
+ $prevTags = $prevTags ? $prevTags : '';
+ $prevTags = array_filter( explode( ',', $prevTags ) );
+ $newTags = array_unique( array_merge( $prevTags, $tags ) );
+ sort($prevTags);
+ sort($newTags);
+
+ if ( $prevTags == $newTags ) {
+ // No change.
+ return false;
+ }
+
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->replace( 'tag_summary', array( 'ts_rev_id', 'ts_rc_id', 'ts_log_id' ), array_filter( array_merge( $tsConds, array( 'ts_tags' => implode( ',', $newTags ) ) ) ), __METHOD__ );
+
+ // Insert the tags rows.
+ $tagsRows = array();
+ foreach( $tags as $tag ) { // Filter so we don't insert NULLs as zero accidentally.
+ $tagsRows[] = array_filter( array( 'ct_tag' => $tag, 'ct_rc_id' => $rc_id, 'ct_log_id' => $log_id, 'ct_rev_id' => $rev_id, 'ct_params' => $params ) );
+ }
+
+ $dbw->insert( 'change_tag', $tagsRows, __METHOD__, array('IGNORE') );
+
+ return true;
+ }
+
+ /**
+ * Applies all tags-related changes to a query.
+ * Handles selecting tags, and filtering.
+ * Needs $tables to be set up properly, so we can figure out which join conditions to use.
+ */
+ static function modifyDisplayQuery( &$tables, &$fields, &$conds, &$join_conds, $filter_tag = false ) {
+ global $wgRequest;
+
+ if ($filter_tag === false) {
+ $filter_tag = $wgRequest->getVal( 'tagfilter' );
+ }
+
+ // Figure out which conditions can be done.
+ $join_field = '';
+ if ( in_array('recentchanges', $tables) ) {
+ $join_cond = 'rc_id';
+ } elseif( in_array('logging', $tables) ) {
+ $join_cond = 'log_id';
+ } elseif ( in_array('revision', $tables) ) {
+ $join_cond = 'rev_id';
+ } else {
+ throw new MWException( "Unable to determine appropriate JOIN condition for tagging." );
+ }
+
+ // JOIN on tag_summary
+ $tables[] = 'tag_summary';
+ $join_conds['tag_summary'] = array( 'LEFT JOIN', "ts_$join_cond=$join_cond" );
+ $fields[] = 'ts_tags';
+
+ if ($filter_tag) {
+ // Somebody wants to filter on a tag.
+ // Add an INNER JOIN on change_tag
+
+ $tables[] = 'change_tag';
+ $join_conds['change_tag'] = array( 'INNER JOIN', "ct_$join_cond=$join_cond" );
+ $conds['ct_tag'] = $filter_tag;
+ }
+ }
+
+ /**
+ * If $fullForm is set to false, then it returns an array of (label, form).
+ * If $fullForm is true, it returns an entire form.
+ */
+ static function buildTagFilterSelector( $selected='', $fullForm = false /* used to put a full form around the selector */ ) {
+ global $wgTitle;
+
+ $data = array( wfMsgExt( 'tag-filter', 'parseinline' ), Xml::input( 'tagfilter', 20, $selected ) );
+
+ if (!$fullForm) {
+ return $data;
+ }
+
+ $html = implode( ' ', $data );
+ $html .= "\n" . Xml::element( 'input', array( 'type' => 'submit', 'value' => wfMsg( 'tag-filter-submit' ) ) );
+ $html .= "\n" . Xml::hidden( 'title', $wgTitle-> getPrefixedText() );
+ $html = Xml::tags( 'form', array( 'action' => $wgTitle->getLocalURL(), 'method' => 'get' ), $html );
+
+ return $html;
+ }
+
+ /** Basically lists defined tags which count even if they aren't applied to anything */
+ static function listDefinedTags() {
+ $emptyTags = array();
+
+ // Some DB stuff
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select( 'valid_tag', 'vt_tag', array(), __METHOD__ );
+ while( $row = $res->fetchObject() ) {
+ $emptyTags[] = $row->vt_tag;
+ }
+
+ wfRunHooks( 'ListDefinedTags', array(&$emptyTags) );
+
+ return array_filter( array_unique( $emptyTags ) );
+ }
+}
\ No newline at end of file
Index: trunk/phase3/includes/LogEventsList.php
===================================================================
--- trunk/phase3/includes/LogEventsList.php (revision 46459)
+++ trunk/phase3/includes/LogEventsList.php (revision 46460)
@@ -68,7 +68,7 @@
* @param $filter Boolean
*/
public function showOptions( $type = '', $user = '', $page = '', $pattern = '', $year = '',
- $month = '', $filter = null )
+ $month = '', $filter = null, $tagFilter='' )
{
global $wgScript, $wgMiserMode;
$action = htmlspecialchars( $wgScript );
@@ -83,7 +83,8 @@
$this->getTitleInput( $page ) . "\n" .
( !$wgMiserMode ? ($this->getTitlePattern( $pattern )."\n") : "" ) .
"<p>" . $this->getDateMenu( $year, $month ) . "\n" .
- ( $filter ? "</p><p>".$this->getFilterLinks( $type, $filter )."\n" : "" ) .
+ Xml::tags( 'p', null, implode( ' ', ChangeTags::buildTagFilterSelector( $tagFilter ) ) ) . "\n" .
+ ( $filter ? "</p><p>".$this->getFilterLinks( $type, $filter )."\n" : "" ) . "\n" .
Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "</p>\n" .
"</fieldset></form>"
);
@@ -230,6 +231,7 @@
global $wgLang, $wgUser, $wgContLang;
$title = Title::makeTitle( $row->log_namespace, $row->log_title );
+ $classes = array( "mw-logline-{$row->log_type}" );
$time = $wgLang->timeanddate( wfTimestamp(TS_MW, $row->log_timestamp), true );
// User links
if( self::isDeleted($row,LogPage::DELETED_USER) ) {
@@ -357,12 +359,16 @@
$this->skin, $paramArray, true );
}
+ // Any tags...
+ list($tagDisplay, $newClasses) = ChangeTags::formatSummaryRow( $row->ts_tags, 'logevent' );
+ $classes = array_merge( $classes, $newClasses );
+
if( $revert != '' ) {
$revert = '<span class="mw-logevent-actionlink">' . $revert . '</span>';
}
- return Xml::tags( 'li', array( "class" => "mw-logline-$row->log_type" ),
- $del . $time . ' ' . $userLink . ' ' . $action . ' ' . $comment . ' ' . $revert ) . "\n";
+ return Xml::tags( 'li', array( "class" => implode( ' ', $classes ) ),
+ $del . $time . ' ' . $userLink . ' ' . $action . ' ' . $comment . ' ' . $revert . " $tagDisplay" ) . "\n";
}
/**
@@ -508,7 +514,7 @@
* @param $month Integer
*/
public function __construct( $list, $type = '', $user = '', $title = '', $pattern = '',
- $conds = array(), $year = false, $month = false )
+ $conds = array(), $year = false, $month = false, $tagFilter = '' )
{
parent::__construct();
$this->mConds = $conds;
@@ -519,6 +525,7 @@
$this->limitUser( $user );
$this->limitTitle( $title, $pattern );
$this->getDateCond( $year, $month );
+ $this->mTagFilter = $tagFilter;
}
public function getDefaultQuery() {
@@ -643,13 +650,18 @@
} else {
$index = array( 'USE INDEX' => array( 'logging' => 'times' ) );
}
- return array(
+ $info = array(
'tables' => array( 'logging', 'user' ),
'fields' => array( 'log_type', 'log_action', 'log_user', 'log_namespace', 'log_title', 'log_params',
'log_comment', 'log_id', 'log_deleted', 'log_timestamp', 'user_name', 'user_editcount' ),
'conds' => $this->mConds,
- 'options' => $index
+ 'options' => $index,
+ 'join_conds' => array( 'user' => array( 'INNER JOIN', 'user_id=log_user' ) ),
);
+
+ ChangeTags::modifyDisplayQuery( $info['tables'], $info['fields'], $info['conds'], $info['join_conds'], $this->mTagFilter );
+
+ return $info;
}
function getIndexField() {
@@ -700,6 +712,10 @@
public function getMonth() {
return $this->mMonth;
}
+
+ public function getTagFilter() {
+ return $this->mTagFilter;
+ }
}
/**
@@ -721,6 +737,7 @@
$pattern = $request->getBool( 'pattern' );
$year = $request->getIntOrNull( 'year' );
$month = $request->getIntOrNull( 'month' );
+ $tagFilter = $request->getVal( 'tagfilter' );
# Don't let the user get stuck with a certain date
$skip = $request->getText( 'offset' ) || $request->getText( 'dir' ) == 'prev';
if( $skip ) {
@@ -729,7 +746,7 @@
}
# Use new list class to output results
$loglist = new LogEventsList( $wgUser->getSkin(), $wgOut, 0 );
- $this->pager = new LogPager( $loglist, $type, $user, $title, $pattern, $year, $month );
+ $this->pager = new LogPager( $loglist, $type, $user, $title, $pattern, $year, $month, $tagFilter );
}
/**
Index: trunk/phase3/includes/AutoLoader.php
===================================================================
--- trunk/phase3/includes/AutoLoader.php (revision 46459)
+++ trunk/phase3/includes/AutoLoader.php (revision 46460)
@@ -28,6 +28,7 @@
'CategoryViewer' => 'includes/CategoryPage.php',
'ChangesList' => 'includes/ChangesList.php',
'ChangesFeed' => 'includes/ChangesFeed.php',
+ 'ChangeTags' => 'includes/ChangeTags.php',
'ChannelFeed' => 'includes/Feed.php',
'ConcatenatedGzipHistoryBlob' => 'includes/HistoryBlob.php',
'ConstantDependency' => 'includes/CacheDependency.php',
@@ -495,6 +496,7 @@
'SpecialSearch' => 'includes/specials/SpecialSearch.php',
'SpecialSearchOld' => 'includes/specials/SpecialSearch.php',
'SpecialStatistics' => 'includes/specials/SpecialStatistics.php',
+ 'SpecialTags' => 'includes/specials/SpecialTags.php',
'SpecialVersion' => 'includes/specials/SpecialVersion.php',
'UncategorizedCategoriesPage' => 'includes/specials/SpecialUncategorizedcategories.php',
'UncategorizedPagesPage' => 'includes/specials/SpecialUncategorizedpages.php',
Index: trunk/phase3/includes/ChangesList.php
===================================================================
--- trunk/phase3/includes/ChangesList.php (revision 46459)
+++ trunk/phase3/includes/ChangesList.php (revision 46460)
@@ -338,6 +338,12 @@
}
}
}
+
+ protected function insertTags( &$s, &$rc, &$classes ) {
+ list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow( $rc->mAttribs['ts_tags'], 'changeslist' );
+ $classes = array_merge( $classes, $newClasses );
+ $s .= ' ' . $tagSummary;
+ }
}
@@ -358,6 +364,7 @@
$this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
$s = '';
+ $classes = array();
// Moved pages
if( $rc->mAttribs['rc_type'] == RC_MOVE || $rc->mAttribs['rc_type'] == RC_MOVE_OVER_REDIRECT ) {
$this->insertMove( $s, $rc );
@@ -394,6 +401,8 @@
$this->insertAction( $s, $rc );
# Edit or log comment
$this->insertComment( $s, $rc );
+ # Tags
+ $this->insertTags( $s, $rc, $classes );
# Rollback
$this->insertRollback( $s, $rc );
# Mark revision as deleted if so
@@ -409,7 +418,7 @@
wfRunHooks( 'OldChangesListRecentChangesLine', array(&$this, &$s, $rc) );
wfProfileOut( __METHOD__ );
- return "$dateheader<li>$s</li>\n";
+ return "$dateheader<li class=\"".implode( ' ', $classes )."\">$s</li>\n";
}
}
Index: trunk/phase3/includes/DefaultSettings.php
===================================================================
--- trunk/phase3/includes/DefaultSettings.php (revision 46459)
+++ trunk/phase3/includes/DefaultSettings.php (revision 46460)
@@ -1455,7 +1455,7 @@
* to ensure that client-side caches don't keep obsolete copies of global
* styles.
*/
-$wgStyleVersion = '201';
+$wgStyleVersion = '202';
# Server-side caching:
Index: trunk/phase3/includes/specials/SpecialRecentchangeslinked.php
===================================================================
--- trunk/phase3/includes/specials/SpecialRecentchangeslinked.php (revision 46459)
+++ trunk/phase3/includes/specials/SpecialRecentchangeslinked.php (revision 46460)
@@ -15,6 +15,7 @@
$opts = parent::getDefaultOptions();
$opts->add( 'target', '' );
$opts->add( 'showlinkedto', false );
+ $opts->add( 'tagfilter', '' );
return $opts;
}
@@ -83,6 +84,8 @@
$join_conds['watchlist'] = array( 'LEFT JOIN', "wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace" );
}
+ ChangeTags::modifyDisplayQuery( $tables, $select, $conds, $join_conds, $opts['tagfilter'] );
+
// XXX: parent class does this, should we too?
// wfRunHooks('SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts ) );
@@ -169,6 +172,7 @@
Xml::input( 'target', 40, str_replace('_',' ',$opts['target']) ) .
Xml::check( 'showlinkedto', $opts['showlinkedto'], array('id' => 'showlinkedto') ) . ' ' .
Xml::label( wfMsg("recentchangeslinked-to"), 'showlinkedto' ) );
+ $extraOpts['tagfilter'] = ChangeTags::buildTagFilterSelector( $opts['tagfilter'] );
return $extraOpts;
}
Index: trunk/phase3/includes/specials/SpecialNewpages.php
===================================================================
--- trunk/phase3/includes/specials/SpecialNewpages.php (revision 46459)
+++ trunk/phase3/includes/specials/SpecialNewpages.php (revision 46460)
@@ -32,6 +32,7 @@
$opts->add( 'namespace', '0' );
$opts->add( 'username', '' );
$opts->add( 'feed', '' );
+ $opts->add( 'tagfilter', '' );
// Set values
$opts->fetchValuesFromRequest( $wgRequest );
@@ -176,6 +177,8 @@
}
$hidden = implode( "\n", $hidden );
+ list( $tagFilterLabel, $tagFilterSelector ) = ChangeTags::buildTagFilterSelector( $this->opts['tagfilter'] );
+
$form = Xml::openElement( 'form', array( 'action' => $wgScript ) ) .
Xml::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) .
Xml::fieldset( wfMsg( 'newpages' ) ) .
@@ -188,6 +191,14 @@
Xml::namespaceSelector( $namespace, 'all' ) .
"</td>
</tr>" .
+ "<tr>
+ <td class='mw-label'>" .
+ $tagFilterLabel .
+ "</td>
+ <td class='mw-input'>" .
+ $tagFilterSelector .
+ "</td>
+ </tr>" .
($wgEnableNewpagesUserFilter ?
"<tr>
<td class='mw-label'>" .
@@ -235,6 +246,9 @@
*/
public function formatRow( $result ) {
global $wgLang, $wgContLang, $wgUser;
+
+ $classes = array();
+
$dm = $wgContLang->getDirMark();
$title = Title::makeTitleSafe( $result->rc_namespace, $result->rc_title );
@@ -247,9 +261,17 @@
$ulink = $this->skin->userLink( $result->rc_user, $result->rc_user_text ) . ' ' .
$this->skin->userToolLinks( $result->rc_user, $result->rc_user_text );
$comment = $this->skin->commentBlock( $result->rc_comment );
- $css = $this->patrollable( $result ) ? " class='not-patrolled'" : '';
+
+ if ( $this->patrollable( $result ) )
+ $classes[] = 'not-patrolled';
- return "<li{$css}>{$time} {$dm}{$plink} ({$hist}) {$dm}[{$length}] {$dm}{$ulink} {$comment}</li>\n";
+ # Tags, if any.
+ list( $tagDisplay, $newClasses ) = ChangeTags::formatSummaryRow( $result->ts_tags, 'newpages' );
+ $classes = array_merge( $classes, $newClasses );
+
+ $css = count($classes) ? ' class="'.implode( " ", $classes).'"' : '';
+
+ return "<li{$css}>{$time} {$dm}{$plink} ({$hist}) {$dm}[{$length}] {$dm}{$ulink} {$comment} {$tagDisplay}</li>\n";
}
/**
@@ -378,7 +400,6 @@
} else {
$rcIndexes = array( 'rc_timestamp' );
}
- $conds[] = 'page_id = rc_cur_id';
# $wgEnableNewpagesUserFilter - temp WMF hack
if( $wgEnableNewpagesUserFilter && $user ) {
@@ -400,13 +421,24 @@
$conds['page_is_redirect'] = 0;
}
- return array(
+ $info = array(
'tables' => array( 'recentchanges', 'page' ),
'fields' => 'rc_namespace,rc_title, rc_cur_id, rc_user,rc_user_text,rc_comment,
- rc_timestamp,rc_patrolled,rc_id,page_len as length, page_latest as rev_id',
+ rc_timestamp,rc_patrolled,rc_id,page_len as length, page_latest as rev_id, ts_tags',
'conds' => $conds,
- 'options' => array( 'USE INDEX' => array('recentchanges' => $rcIndexes) )
+ 'options' => array( 'USE INDEX' => array('recentchanges' => $rcIndexes) ),
+ 'join_conds' => array(
+ 'page' => array('INNER JOIN', 'page_id=rc_cur_id'),
+ ),
);
+
+ ## Empty array for fields, it'll be set by us anyway.
+ $fields = array();
+
+ ## Modify query for tags
+ ChangeTags::modifyDisplayQuery( $info['tables'], $fields, $info['conds'], $info['join_conds'], $this->opts['tagfilter'] );
+
+ return $info;
}
function getIndexField() {
Index: trunk/phase3/includes/specials/SpecialLog.php
===================================================================
--- trunk/phase3/includes/specials/SpecialLog.php (revision 46459)
+++ trunk/phase3/includes/specials/SpecialLog.php (revision 46460)
@@ -45,6 +45,7 @@
$pattern = $wgRequest->getBool( 'pattern' );
$y = $wgRequest->getIntOrNull( 'year' );
$m = $wgRequest->getIntOrNull( 'month' );
+ $tagFilter = $wgRequest->getVal( 'tagfilter' );
# Don't let the user get stuck with a certain date
$skip = $wgRequest->getText( 'offset' ) || $wgRequest->getText( 'dir' ) == 'prev';
if( $skip ) {
@@ -53,12 +54,12 @@
}
# Create a LogPager item to get the results and a LogEventsList item to format them...
$loglist = new LogEventsList( $wgUser->getSkin(), $wgOut, 0 );
- $pager = new LogPager( $loglist, $type, $user, $title, $pattern, array(), $y, $m );
+ $pager = new LogPager( $loglist, $type, $user, $title, $pattern, array(), $y, $m, $tagFilter );
# Set title and add header
$loglist->showHeader( $pager->getType() );
# Show form options
$loglist->showOptions( $pager->getType(), $pager->getUser(), $pager->getPage(), $pager->getPattern(),
- $pager->getYear(), $pager->getMonth(), $pager->getFilterParams() );
+ $pager->getYear(), $pager->getMonth(), $pager->getFilterParams(), $tagFilter );
# Insert list
$logBody = $pager->getBody();
if( $logBody ) {
Index: trunk/phase3/includes/specials/SpecialRecentchanges.php
===================================================================
--- trunk/phase3/includes/specials/SpecialRecentchanges.php (revision 46459)
+++ trunk/phase3/includes/specials/SpecialRecentchanges.php (revision 46460)
@@ -35,6 +35,7 @@
$opts->add( 'categories', '' );
$opts->add( 'categories_any', false );
+ $opts->add( 'tagfilter', '' );
return $opts;
}
@@ -275,13 +276,19 @@
$namespace = $opts['namespace'];
$invert = $opts['invert'];
+ $join_conds = array();
+
// JOIN on watchlist for users
if( $uid ) {
$tables[] = 'watchlist';
- $join_conds = array( 'watchlist' => array('LEFT JOIN',
- "wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace") );
+ $join_conds['watchlist'] = array('LEFT JOIN',
+ "wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace");
}
+ // Tag stuff.
+ $fields = array(); // Fields are * in this case, so let the function modify an empty array to keep it happy.
+ ChangeTags::modifyDisplayQuery( &$tables, $fields, &$conds, &$join_conds, $opts['tagfilter'] );
+
wfRunHooks('SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts ) );
// Is there either one namespace selected or excluded?
@@ -454,6 +461,8 @@
$extraOpts['category'] = $this->categoryFilterForm( $opts );
}
+ $extraOpts['tagfilter'] = ChangeTags::buildTagFilterSelector( $opts['tagfilter'] );
+
wfRunHooks( 'SpecialRecentChangesPanel', array( &$extraOpts, $opts ) );
return $extraOpts;
}
Index: trunk/phase3/includes/specials/SpecialContributions.php
===================================================================
--- trunk/phase3/includes/specials/SpecialContributions.php (revision 46459)
+++ trunk/phase3/includes/specials/SpecialContributions.php (revision 46460)
@@ -63,6 +63,8 @@
} else {
$this->opts['namespace'] = '';
}
+
+ $this->opts['tagfilter'] = $wgRequest->getVal( 'tagfilter' );
// Allows reverts to have the bot flag in recent changes. It is just here to
// be passed in the form at the top of the page
@@ -256,6 +258,7 @@
Xml::label( wfMsg( 'namespace' ), 'namespace' ) . ' ' .
Xml::namespaceSelector( $this->opts['namespace'], '' ) .
'</span>' .
+ Xml::tags( 'p', null, implode( ' ', ChangeTags::buildTagFilterSelector( $this->opts['tagfilter'] ) ) ) .
Xml::openElement( 'p' ) .
'<span style="white-space: nowrap">' .
Xml::label( wfMsg( 'year' ), 'year' ) . ' '.
@@ -307,7 +310,7 @@
$target = $this->opts['target'] == 'newbies' ? 'newbies' : $nt->getText();
$pager = new ContribsPager( $target, $this->opts['namespace'],
- $this->opts['year'], $this->opts['month'] );
+ $this->opts['year'], $this->opts['month'], $this->opts['tagfilter'] );
$pager->mLimit = min( $this->opts['limit'], $wgFeedLimit );
@@ -371,13 +374,14 @@
var $messages, $target;
var $namespace = '', $mDb;
- function __construct( $target, $namespace = false, $year = false, $month = false ) {
+ function __construct( $target, $namespace = false, $year = false, $month = false, $tagFilter = false ) {
parent::__construct();
foreach( explode( ' ', 'uctop diff newarticle rollbacklink diff hist newpageletter minoreditletter' ) as $msg ) {
$this->messages[$msg] = wfMsgExt( $msg, array( 'escape') );
}
$this->target = $target;
$this->namespace = $namespace;
+ $this->tagFilter = $tagFilter;
$this->getDateCond( $year, $month );
@@ -392,7 +396,10 @@
function getQueryInfo() {
list( $tables, $index, $userCond, $join_cond ) = $this->getUserCond();
- $conds = array_merge( array('page_id=rev_page'), $userCond, $this->getNamespaceCond() );
+
+ $conds = array_merge( $userCond, $this->getNamespaceCond() );
+ $join_cond['page'] = array( 'INNER JOIN', 'page_id=rev_page' );
+
$queryInfo = array(
'tables' => $tables,
'fields' => array(
@@ -404,6 +411,9 @@
'options' => array( 'USE INDEX' => array('revision' => $index) ),
'join_conds' => $join_cond
);
+
+ ChangeTags::modifyDisplayQuery( $queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], $queryInfo['join_conds'], $this->tagFilter );
+
wfRunHooks( 'ContribsPager::getQueryInfo', array( &$this, &$queryInfo ) );
return $queryInfo;
}
@@ -463,6 +473,7 @@
$sk = $this->getSkin();
$rev = new Revision( $row );
+ $classes = array();
$page = Title::newFromRow( $row );
$page->resetArticleId( $row->rev_page ); // use process cache
@@ -521,10 +532,17 @@
if( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
$ret .= ' ' . wfMsgHtml( 'deletedrev' );
}
+
+ # Tags, if any.
+ list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow( $row->ts_tags, 'contributions' );
+ $classes = array_merge( $classes, $newClasses );
+ $ret .= " $tagSummary";
+
// Let extensions add data
wfRunHooks( 'ContributionsLineEnding', array( &$this, &$ret, $row ) );
-
- $ret = "<li>$ret</li>\n";
+
+ $classes = implode( ' ', $classes );
+ $ret = "<li class=\"$classes\">$ret</li>\n";
wfProfileOut( __METHOD__ );
return $ret;
}
Index: trunk/phase3/includes/specials/SpecialTags.php
===================================================================
--- trunk/phase3/includes/specials/SpecialTags.php (revision 0)
+++ trunk/phase3/includes/specials/SpecialTags.php (revision 46460)
@@ -0,0 +1,75 @@
+<?php
+
+if (!defined('MEDIAWIKI'))
+ die;
+
+class SpecialTags extends SpecialPage {
+
+ function __construct() {
+ parent::__construct( 'Tags' );
+ }
+
+ function execute() {
+ global $wgOut, $wgUser, $wgMessageCache;
+
+ $wgMessageCache->loadAllMessages();
+
+ $sk = $wgUser->getSkin();
+ $wgOut->setPageTitle( wfMsg( 'tags-title' ) );
+ $wgOut->addWikiMsg( 'tags-intro' );
+
+ // Write the headers
+ $html = '';
+ $html = Xml::tags( 'tr', null, Xml::tags( 'th', null, wfMsgExt( 'tags-tag', 'parseinline' ) ) .
+ Xml::tags( 'th', null, wfMsgExt( 'tags-display-header', 'parseinline' ) ) .
+ Xml::tags( 'th', null, wfMsgExt( 'tags-description-header', 'parseinline' ) ) .
+ Xml::tags( 'th', null, wfMsgExt( 'tags-hitcount-header', 'parseinline' ) )
+ );
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select( 'change_tag', array( 'ct_tag', 'count(*) as hitcount' ), array(), __METHOD__, array( 'GROUP BY' => 'ct_tag', 'ORDER BY' => 'hitcount DESC' ) );
+
+ while ( $row = $res->fetchObject() ) {
+ $html .= $this->doTagRow( $row->ct_tag, $row->hitcount );
+ }
+
+ foreach( ChangeTags::listDefinedTags() as $tag ) {
+ $html .= $this->doTagRow( $tag, 0 );
+ }
+
+ $html = "<table style='width: 80%'><tbody>$html</tbody></table>";
+
+ $wgOut->addHTML( $html );
+ }
+
+ function doTagRow( $tag, $hitcount ) {
+ static $sk=null, $doneTags=array();
+ if (!$sk) {
+ global $wgUser;
+ $sk = $wgUser->getSkin();
+ }
+
+ if ( in_array( $tag, $doneTags ) ) {
+ return '';
+ }
+
+ $newRow = '';
+ $newRow .= Xml::tags( 'td', null, Xml::element( 'tt', null, $tag ) );
+
+ $disp = ChangeTags::tagDescription( $tag );
+ $disp .= ' (' . $sk->link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag" ), wfMsg( 'tag-edit' ) ) . ')';
+ $newRow .= Xml::tags( 'td', null, $disp );
+
+ $desc = wfMsgExt( "tag-$tag-description", 'parseinline' );
+ $desc = wfEmptyMsg( "tag-$tag-description", $desc ) ? '' : $desc;
+ $desc .= ' (' . $sk->link( Title::makeTitle( NS_MEDIAWIKI, "Tag-$tag-description" ), wfMsg( 'tag-edit' ) ) . ')';
+ $newRow .= Xml::tags( 'td', null, $desc );
+
+ $hitcount = wfMsg( 'tags-hitcount', $hitcount );
+ $hitcount = $sk->link( SpecialPage::getTitleFor( 'RecentChanges' ), $hitcount, array(), array( 'tagfilter' => $tag ) );
+ $newRow .= Xml::tags( 'td', null, $hitcount );
+
+ $doneTags[] = $tag;
+
+ return Xml::tags( 'tr', null, $newRow ) . "\n";
+ }
+}
\ No newline at end of file
Index: trunk/phase3/includes/specials/SpecialWatchlist.php
===================================================================
--- trunk/phase3/includes/specials/SpecialWatchlist.php (revision 46459)
+++ trunk/phase3/includes/specials/SpecialWatchlist.php (revision 46460)
@@ -218,7 +218,8 @@
$tables[] = 'page';
$join_conds['page'] = array('LEFT JOIN','rc_cur_id=page_id');
}
-
+
+ ChangeTags::modifyDisplayQuery( $tables, $fields, $conds, $join_conds, '' );
wfRunHooks('SpecialWatchlistQuery', array(&$conds,&$tables,&$join_conds,&$fields) );
$res = $dbr->select( $tables, $fields, $conds, __METHOD__, $options, $join_conds );
Index: trunk/phase3/includes/PageHistory.php
===================================================================
--- trunk/phase3/includes/PageHistory.php (revision 46459)
+++ trunk/phase3/includes/PageHistory.php (revision 46460)
@@ -112,6 +112,7 @@
*/
$year = $wgRequest->getInt( 'year' );
$month = $wgRequest->getInt( 'month' );
+ $tagFilter = $wgRequest->getVal( 'tagfilter' );
$action = htmlspecialchars( $wgScript );
$wgOut->addHTML(
@@ -120,6 +121,7 @@
Xml::hidden( 'title', $this->mTitle->getPrefixedDBKey() ) . "\n" .
Xml::hidden( 'action', 'history' ) . "\n" .
$this->getDateMenu( $year, $month ) . ' ' .
+ implode( ' ', ChangeTags::buildTagFilterSelector( $tagFilter ) ) . ' ' .
Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
'</fieldset></form>'
);
@@ -129,7 +131,7 @@
/**
* Do the list
*/
- $pager = new PageHistoryPager( $this, $year, $month );
+ $pager = new PageHistoryPager( $this, $year, $month, $tagFilter );
$this->linesonpage = $pager->getNumRows();
$wgOut->addHTML(
$pager->getNavigationBar() .
@@ -287,6 +289,7 @@
$lastlink = $this->lastLink( $rev, $next, $counter );
$arbitrary = $this->diffButtons( $rev, $firstInList, $counter );
$link = $this->revLink( $rev );
+ $classes = array();
$s = "($curlink) ($lastlink) $arbitrary";
@@ -355,9 +358,16 @@
$s .= ' (' . implode( ' | ', $tools ) . ')';
}
+ # Tags
+ list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow( $row->ts_tags, 'history' );
+ $classes = array_merge( $classes, $newClasses );
+ $s .= " $tagSummary";
+
wfRunHooks( 'PageHistoryLineEnding', array( $this, &$row , &$s ) );
- return "<li>$s</li>\n";
+ $classes = implode( ' ', $classes );
+
+ return "<li class=\"$classes\">$s</li>\n";
}
/**
@@ -589,20 +599,23 @@
class PageHistoryPager extends ReverseChronologicalPager {
public $mLastRow = false, $mPageHistory, $mTitle;
- function __construct( $pageHistory, $year='', $month='' ) {
+ function __construct( $pageHistory, $year='', $month='', $tagFilter = '' ) {
parent::__construct();
$this->mPageHistory = $pageHistory;
$this->mTitle =& $this->mPageHistory->mTitle;
+ $this->tagFilter = $tagFilter;
$this->getDateCond( $year, $month );
}
function getQueryInfo() {
$queryInfo = array(
'tables' => array('revision'),
- 'fields' => Revision::selectFields(),
+ 'fields' => array_merge( Revision::selectFields(), array('ts_tags') ),
'conds' => array('rev_page' => $this->mPageHistory->mTitle->getArticleID() ),
- 'options' => array( 'USE INDEX' => array('revision' => 'page_timestamp') )
+ 'options' => array( 'USE INDEX' => array('revision' => 'page_timestamp') ),
+ 'join_conds' => array( 'tag_summary' => array( 'LEFT JOIN', 'ts_rev_id=rev_id' ) ),
);
+ ChangeTags::modifyDisplayQuery( $queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], $queryInfo['join_conds'], $this->tagFilter );
wfRunHooks( 'PageHistoryPager::getQueryInfo', array( &$this, &$queryInfo ) );
return $queryInfo;
}
Index: trunk/phase3/includes/SpecialPage.php
===================================================================
--- trunk/phase3/includes/SpecialPage.php (revision 46459)
+++ trunk/phase3/includes/SpecialPage.php (revision 46460)
@@ -159,6 +159,7 @@
'Randomredirect' => 'SpecialRandomredirect',
'Withoutinterwiki' => array( 'SpecialPage', 'Withoutinterwiki' ),
'Filepath' => array( 'SpecialPage', 'Filepath' ),
+ 'Tags' => 'SpecialTags',
'Mypage' => array( 'SpecialMypage' ),
'Mytalk' => array( 'SpecialMytalk' ),
Index: trunk/phase3/languages/messages/MessagesEn.php
===================================================================
--- trunk/phase3/languages/messages/MessagesEn.php (revision 46459)
+++ trunk/phase3/languages/messages/MessagesEn.php (revision 46460)
@@ -3801,4 +3801,15 @@
#Put all regex fragments above this line. Leave this line exactly as it is</pre>',
+## Taggng-related stuff
+'tag-filter' => '[[Special:Tags|Tag]] filter:',
+'tag-filter-submit' => 'Filter',
+'tags-title' => 'Tags',
+'tags-intro' => 'This page lists the tags that the software may mark an edit with, and their meaning.',
+'tags-tag' => 'Internal tag name',
+'tags-display-header' => 'Appearance on change lists',
+'tags-description-header' => 'Full description of meaning',
+'tags-hitcount-header' => 'Tagged edits',
+'tags-edit' => 'edit',
+'tags-hitcount' => '$1 changes',
);
Index: trunk/extensions/TorBlock/TorBlock.i18n.php
===================================================================
--- trunk/extensions/TorBlock/TorBlock.i18n.php (revision 46459)
+++ trunk/extensions/TorBlock/TorBlock.i18n.php (revision 46460)
@@ -15,6 +15,8 @@
'torblock-blocked' => 'Your IP address, <tt>$1</tt>, has been automatically identified as a tor exit node.
Editing through tor is blocked to prevent abuse.',
'right-torunblocked' => 'Bypass automatic blocks of tor exit nodes',
+ 'tag-tor-description' => 'If this tag is set, an edit was made from a Tor exit node.',
+ 'tag-tor' => 'Made through tor',
);
/** Message documentation (Message documentation)
Index: trunk/extensions/TorBlock/TorBlock.php
===================================================================
--- trunk/extensions/TorBlock/TorBlock.php (revision 46459)
+++ trunk/extensions/TorBlock/TorBlock.php (revision 46460)
@@ -33,6 +33,8 @@
$wgHooks['GetAutoPromoteGroups'][] = 'TorBlock::onGetAutoPromoteGroups';
$wgHooks['GetBlockedStatus'][] = 'TorBlock::onGetBlockedStatus';
$wgHooks['AutopromoteCondition'][] = 'TorBlock::onAutopromoteCondition';
+$wgHooks['RecentChange_save'][] = 'TorBlock::onRecentChangeSave';
+$wgHooks['ListDefinedTags'][] = 'TorBlock::onListDefinedTags';
// Define new autopromote condition
define('APCOND_TOR', 'tor'); // Numbers won't work, we'll get collisions
Index: trunk/extensions/TorBlock/TorBlock.class.php
===================================================================
--- trunk/extensions/TorBlock/TorBlock.class.php (revision 46459)
+++ trunk/extensions/TorBlock/TorBlock.class.php (revision 46460)
@@ -168,4 +168,16 @@
return true;
}
+
+ public static function onRecentChangeSave( $recentChange ) {
+ if ( class_exists('ChangeTags') && self::isExitNode() ) {
+ ChangeTags::addTags( 'tor', $recentChange->mAttribs['rc_id'], $recentChange->mAttribs['rc_this_oldid'], $recentChange->mAttribs['rc_logid'] );
+ }
+ return true;
+ }
+
+ public static function onListDefinedTags( &$emptyTags ) {
+ $emptyTags[] = 'tor';
+ return true;
+ }
}
Index: trunk/extensions/AbuseFilter/AbuseFilter.php
===================================================================
--- trunk/extensions/AbuseFilter/AbuseFilter.php (revision 46459)
+++ trunk/extensions/AbuseFilter/AbuseFilter.php (revision 46460)
@@ -52,8 +52,8 @@
$wgHooks['ArticleDelete'][] = 'AbuseFilterHooks::onArticleDelete';
$wgHooks['LoadExtensionSchemaUpdates'][] = 'AbuseFilterHooks::onSchemaUpdate';
$wgHooks['AbortDeleteQueueNominate'][] = 'AbuseFilterHooks::onAbortDeleteQueueNominate';
-// $wgHooks['RecentChange_save'][] = 'AbuseFilterHooks::onRecentChangeSave';
-// $wgHooks['ListDefinedTags'][] = 'AbuseFilterHooks::onListDefinedTags';
+$wgHooks['RecentChange_save'][] = 'AbuseFilterHooks::onRecentChangeSave';
+$wgHooks['ListDefinedTags'][] = 'AbuseFilterHooks::onListDefinedTags';
$wgAvailableRights[] = 'abusefilter-modify';
$wgAvailableRights[] = 'abusefilter-log-detail';
@@ -63,7 +63,7 @@
$wgAvailableRights[] = 'abusefilter-modify-restricted';
$wgAvailableRights[] = 'abusefilter-revert';
-$wgAbuseFilterAvailableActions = array( 'flag', 'throttle', 'warn', 'disallow', 'blockautopromote', 'block', 'degroup', /* Disabled because it's ridiculously excessive 'rangeblock'*/ /*, 'tag' Disabled for now to avoid trunk changes. */ );
+$wgAbuseFilterAvailableActions = array( 'flag', 'throttle', 'warn', 'disallow', 'blockautopromote', 'block', 'degroup', 'tag' );
$wgAbuseFilterConditionLimit = 1000;
Index: trunk/extensions/AbuseFilter/Views/AbuseFilterViewEdit.php
===================================================================
--- trunk/extensions/AbuseFilter/Views/AbuseFilterViewEdit.php (revision 46459)
+++ trunk/extensions/AbuseFilter/Views/AbuseFilterViewEdit.php (revision 46460)
@@ -328,21 +328,20 @@
$warnFields['abusefilter-edit-warn-message'] = Xml::input( 'wpFilterWarnMessage', 45, $warnMsg );
$output .= Xml::tags( 'p', null, Xml::buildForm( $warnFields ) );
return $output;
- // Commented out to avoid trunk changes for now.
-// case 'tag':
-// if ($set) {
-// $tags = $parameters;
-// } else {
-// $tags = array();
-// }
-// $output = '';
-//
-// $checkbox = Xml::checkLabel( wfMsg('abusefilter-edit-action-tag'), 'wpFilterActionTag', 'wpFilterActionTag', $set );
-// $output .= Xml::tags( 'p', null, $checkbox );
-//
-// $tagFields['abusefilter-edit-tag-tag'] = Xml::textarea( 'wpFilterTags', implode( "\n", $tags ) );
-// $output .= Xml::tags( 'p', null, Xml::buildForm( $tagFields ) );
-// return $output;
+ case 'tag':
+ if ($set) {
+ $tags = $parameters;
+ } else {
+ $tags = array();
+ }
+ $output = '';
+
+ $checkbox = Xml::checkLabel( wfMsg('abusefilter-edit-action-tag'), 'wpFilterActionTag', 'wpFilterActionTag', $set );
+ $output .= Xml::tags( 'p', null, $checkbox );
+
+ $tagFields['abusefilter-edit-tag-tag'] = Xml::textarea( 'wpFilterTags', implode( "\n", $tags ) );
+ $output .= Xml::tags( 'p', null, Xml::buildForm( $tagFields ) );
+ return $output;
default:
$message = 'abusefilter-edit-action-'.$action;
$form_field = 'wpFilterAction' . ucfirst($action);
Index: trunk/extensions/AbuseFilter/AbuseFilter.class.php
===================================================================
--- trunk/extensions/AbuseFilter/AbuseFilter.class.php (revision 46459)
+++ trunk/extensions/AbuseFilter/AbuseFilter.class.php (revision 46460)
@@ -439,16 +439,18 @@
// Do nothing. Here for completeness.
break;
-// case 'tag':
-// // Mark with a tag on recentchanges.
-// global $wgUser;
-//
-// $actionID = implode( '-', array(
-// $title->getPrefixedText(), $wgUser->getName(), $vars['ACTION']
-// ) );
-//
-// AbuseFilter::$tagsToSet[$actionID] = $parameters;
-// break;
+ case 'tag':
+ // Mark with a tag on recentchanges.
+ global $wgUser;
+
+ $actionID = implode( '-', array(
+ $title->getPrefixedText(), $wgUser->getName(), $vars['ACTION']
+ ) );
+
+ AbuseFilter::$tagsToSet[$actionID] = $parameters;
+ break;
+ default:
+ throw new MWException( "Unrecognised action $action" );
}
return $display;
Index: trunk/extensions/AbuseFilter/AbuseFilter.hooks.php
===================================================================
--- trunk/extensions/AbuseFilter/AbuseFilter.hooks.php (revision 46459)
+++ trunk/extensions/AbuseFilter/AbuseFilter.hooks.php (revision 46460)
@@ -172,31 +172,30 @@
return $filter_result == '' || $filter_result === true;
}
-// Commented out to avoid trunk changes for now.
-// public static function onRecentChangeSave( $recentChange ) {
-// $title = Title::makeTitle( $recentChange->mAttribs['rc_namespace'], $recentChange->mAttribs['rc_title'] );
-// $action = $recentChange->mAttribs['rc_log_type'] ? $recentChange->mAttribs['rc_log_type'] : 'edit';
-// $actionID = implode( '-', array(
-// $title->getPrefixedText(), $recentChange->mAttribs['rc_user_text'], $action
-// ) );
-//
-// if ( !empty( AbuseFilter::$tagsToSet[$actionID] ) && count( $tags = AbuseFilter::$tagsToSet[$actionID]) ) {
-// ChangeTags::addTags( $tags, $recentChange->mAttribs['rc_id'], $recentChange->mAttribs['rc_this_oldid'], $recentChange->mAttribs['rc_logid'] );
-// }
-//
-// return true;
-// }
+ public static function onRecentChangeSave( $recentChange ) {
+ $title = Title::makeTitle( $recentChange->mAttribs['rc_namespace'], $recentChange->mAttribs['rc_title'] );
+ $action = $recentChange->mAttribs['rc_log_type'] ? $recentChange->mAttribs['rc_log_type'] : 'edit';
+ $actionID = implode( '-', array(
+ $title->getPrefixedText(), $recentChange->mAttribs['rc_user_text'], $action
+ ) );
-// public static function onListDefinedTags( &$emptyTags ) {
-// ## This is a pretty awful hack.
-// $dbr = wfGetDB( DB_SLAVE );
-//
-// $res = $dbr->select( 'abuse_filter_action', 'afa_parameters', array( 'afa_consequence' => 'tag' ), __METHOD__ );
-//
-// while( $row = $res->fetchObject() ) {
-// $emptyTags = array_filter( array_merge( explode( "\n", $row->afa_parameters ), $emptyTags ) );
-// }
-//
-// return true;
-// }
+ if ( !empty( AbuseFilter::$tagsToSet[$actionID] ) && count( $tags = AbuseFilter::$tagsToSet[$actionID]) ) {
+ ChangeTags::addTags( $tags, $recentChange->mAttribs['rc_id'], $recentChange->mAttribs['rc_this_oldid'], $recentChange->mAttribs['rc_logid'] );
+ }
+
+ return true;
+ }
+
+ public static function onListDefinedTags( &$emptyTags ) {
+ ## This is a pretty awful hack.
+ $dbr = wfGetDB( DB_SLAVE );
+
+ $res = $dbr->select( 'abuse_filter_action', 'afa_parameters', array( 'afa_consequence' => 'tag' ), __METHOD__ );
+
+ while( $row = $res->fetchObject() ) {
+ $emptyTags = array_filter( array_merge( explode( "\n", $row->afa_parameters ), $emptyTags ) );
+ }
+
+ return true;
+ }
}