MediaWiki r46557 - Code Review

Jump to: navigation, search
Repository:MediaWiki
Revision:r46556‎ | r46557 (on ViewVC)‎ | r46558 >
Date:22:44, 29 January 2009
Author:werdna
Status:deferred
Tags:
Comment:
Abuse Filter changes designed for testing filters against real data:
* Add searching and filtering functionality to the existing 'test' interface.
* Add an 'examine' interface designed for testing filters against a previous change, selectable through the search interface in either the 'test' or the 'examine' view.
* Minor enabling change in ChangesList core, to allow subclassing.
Modified paths:

Diff [purge]

Index: trunk/phase3/includes/ChangesList.php
===================================================================
--- trunk/phase3/includes/ChangesList.php	(revision 46556)
+++ trunk/phase3/includes/ChangesList.php	(revision 46557)
@@ -347,6 +347,10 @@
 		$classes = array_merge( $classes, $newClasses );
 		$s .= ' ' . $tagSummary;
 	}
+
+	protected function insertExtra( &$s, &$rc, &$classes ) {
+		## Empty, used for subclassers to add anything special.
+	}
 }
 
 
@@ -408,6 +412,9 @@
 		$this->insertTags( $s, $rc, $classes );
 		# Rollback
 		$this->insertRollback( $s, $rc );
+		# For subclasses
+		$this->insertExtra( $s, $rc, $classes );
+		
 		# Mark revision as deleted if so
 		if( !$rc->mAttribs['rc_log_type'] && $this->isDeleted($rc,Revision::DELETED_TEXT) ) {
 		   $s .= ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
Index: trunk/extensions/AbuseFilter/SpecialAbuseLog.php
===================================================================
--- trunk/extensions/AbuseFilter/SpecialAbuseLog.php	(revision 46556)
+++ trunk/extensions/AbuseFilter/SpecialAbuseLog.php	(revision 46557)
@@ -101,11 +101,6 @@
 		if (!$this->canSeeDetails()) {
 			return;
 		}
-
-		// I don't want to change the names of the pre-existing messages
-		// describing the variables, nor do I want to rewrite them, so I'm just
-		// mapping the variable names to builder messages with a pre-existing array.
-		$variableMessageMappings = AbuseFilter::$builderValues['vars'];
 		
 		$dbr = wfGetDB( DB_SLAVE );
 		
@@ -123,28 +118,8 @@
 		// Build a table.
 		$vars = unserialize( $row->afl_var_dump );
 		
-		$output .= Xml::openElement( 'table', array( 'class' => 'mw-abuselog-details' ) ) . Xml::openElement( 'tbody' );
+		$output .= AbuseFilter::buildVarDumpTable( $vars );
 		
-		$header = Xml::element( 'th', null, wfMsg( 'abusefilter-log-details-var' ) ) . Xml::element( 'th', null, wfMsg( 'abusefilter-log-details-val' ) );
-		$output .= Xml::tags( 'tr', null, $header );
-		
-		// Now, build the body of the table.
-		foreach( $vars as $key => $value ) {
-			if ( !empty($variableMessageMappings[$key]) ) {
-				$mapping = $variableMessageMappings[$key];
-				$keyDisplay = wfMsgExt( "abusefilter-edit-builder-vars-$mapping", 'parseinline' ) . ' (' . Xml::element( 'tt', null, $key ) . ')';
-			} else {
-				$keyDisplay = Xml::element( 'tt', null, $key );
-			}
-
-			$value = Xml::element( 'div', array( 'class' => 'mw-abuselog-var-value' ), $value );
-			
-			$trow = Xml::tags( 'td', array( 'class' => 'mw-abuselog-var' ), $keyDisplay ) . Xml::tags( 'td', array( 'class' => 'mw-abuselog-var-value' ), $value );
-			$output .= Xml::tags( 'tr', array( 'class' => "mw-abuselog-details-$key mw-abuselog-value" ), $trow );
-		}
-		
-		$output .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
-		
 		if ($this->canSeePrivate()) {
 			// Private stuff, like IPs.
 			$output .= Xml::element( 'h3', null, wfMsg( 'abusefilter-log-details-private' ) );
Index: trunk/extensions/AbuseFilter/AbuseFilter.php
===================================================================
--- trunk/extensions/AbuseFilter/AbuseFilter.php	(revision 46556)
+++ trunk/extensions/AbuseFilter/AbuseFilter.php	(revision 46557)
@@ -39,7 +39,9 @@
 $wgAutoloadClasses['AbuseFilterViewTools'] = "$dir/Views/AbuseFilterViewTools.php";
 $wgAutoloadClasses['AbuseFilterViewHistory'] = "$dir/Views/AbuseFilterViewHistory.php";
 $wgAutoloadClasses['AbuseFilterViewRevert'] = "$dir/Views/AbuseFilterViewRevert.php";
-$wgAutoloadClasses['AbuseFilterViewTest'] = "$dir/Views/AbuseFilterViewTest.php";
+$wgAutoloadClasses['AbuseFilterViewTestBatch'] = "$dir/Views/AbuseFilterViewTestBatch.php";
+$wgAutoloadClasses['AbuseFilterViewExamine'] = "$dir/Views/AbuseFilterViewExamine.php";
+$wgAutoloadClasses['AbuseFilterChangesList'] = "$dir/Views/AbuseFilterViewExamine.php";
 
 $wgSpecialPages['AbuseLog'] = 'SpecialAbuseLog';
 $wgSpecialPages['AbuseFilter'] = 'SpecialAbuseFilter';
@@ -84,6 +86,7 @@
 $wgAjaxExportList[] = 'AbuseFilter::ajaxEvaluateExpression';
 $wgAjaxExportList[] = 'AbuseFilter::ajaxReAutoconfirm';
 $wgAjaxExportList[] = 'AbuseFilter::ajaxGetFilter';
+$wgAjaxExportList[] = 'AbuseFilter::ajaxCheckFilterWithVars';
 
 // Bump the version number every time you change any of the .css/.js files
 $wgAbuseFilterStyleVersion = 3;
Index: trunk/extensions/AbuseFilter/SpecialAbuseFilter.php
===================================================================
--- trunk/extensions/AbuseFilter/SpecialAbuseFilter.php	(revision 46556)
+++ trunk/extensions/AbuseFilter/SpecialAbuseFilter.php	(revision 46557)
@@ -50,9 +50,13 @@
 			$view = 'AbuseFilterViewRevert';
 		}
 
-		if ( !empty($params[0]) && $params[0] == 'test' ) {
-			$view = 'AbuseFilterViewTest';
+		if ( $subpage == 'test' ) {
+			$view = 'AbuseFilterViewTestBatch';
 		}
+
+		if ( count($params) && $params[0] == 'examine' ) {
+			$view = 'AbuseFilterViewExamine';
+		}
 		
 		if (!empty($params[0]) && ($params[0] == 'history' || $params[0] == 'log') ) {
 			if (count($params) == 1) {
Index: trunk/extensions/AbuseFilter/Views/AbuseFilterViewTest.php
===================================================================
--- trunk/extensions/AbuseFilter/Views/AbuseFilterViewTest.php	(revision 46556)
+++ trunk/extensions/AbuseFilter/Views/AbuseFilterViewTest.php	(revision 46557)
@@ -1,84 +0,0 @@
-<?php
-
-if (!defined( 'MEDIAWIKI' ))
-	die();
-
-class AbuseFilterViewTest extends AbuseFilterView {
-	// Hard-coded for now.
-	static $mChangeLimit = 100;
-	
-	function show( ) {
-		global $wgOut, $wgUser, $wgRequest;
-		
-		AbuseFilter::disableConditionLimit();
-
-		$this->loadParameters();
-		
-		$wgOut->setPageTitle( wfMsg( 'abusefilter-test' ) );
-		$wgOut->addWikiMsg( 'abusefilter-test-intro', self::$mChangeLimit );
-
-		$output = '';
-		$output .= AbuseFilter::buildEditBox( $this->mFilter, 'wpTestFilter' ) . "\n";
-		$output .= Xml::inputLabel( wfMsg( 'abusefilter-test-load-filter' ), 'wpInsertFilter', 'mw-abusefilter-load-filter', 10, '' ) . '&nbsp;' .
-			Xml::element( 'input', array( 'type' => 'button', 'value' => wfMsg( 'abusefilter-test-load' ), 'id' => 'mw-abusefilter-load' ) );
-		$output = Xml::tags( 'div', array( 'id' => 'mw-abusefilter-test-editor' ), $output );
-
-		// Removed until I can distinguish between positives and negatives :)
-// 		$output .= Xml::tags( 'p', null, Xml::checkLabel( wfMsg( 'abusefilter-test-shownegative' ), 'wpShowNegative', 'wpShowNegative', $this->mShowNegative ) );
-		$output .= Xml::tags( 'p', null, Xml::submitButton( wfMsg( 'abusefilter-test-submit' ) ) );
-		$output .= Xml::hidden( 'title', $this->getTitle("test")->getPrefixedText() );
-		$output = Xml::tags( 'form', array( 'action' => $this->getTitle("test")->getLocalURL(), 'method' => 'POST' ), $output );
-
-		$output = Xml::fieldset( wfMsg( 'abusefilter-test-legend' ), $output );
-
-		$wgOut->addHTML( $output );
-
-		if ($wgRequest->wasPosted()) {
-			$this->doTest();
-		}
-	}
-
-	function doTest() {
-		// Quick syntax check.
-		if ( ($result = AbuseFilter::checkSyntax( $this->mFilter )) !== true ) {
-			$wgOut->addWikiMsg( 'abusefilter-test-syntaxerr' );
-			return;
-		}
-
-		// Get our ChangesList
-		global $wgUser, $wgOut;
-		$changesList = ChangesList::newFromUser( $wgUser );
-		$output = $changesList->beginRecentChangesList();
-
-		$dbr = wfGetDB( DB_SLAVE );
-		$res = $dbr->select( 'recentchanges', '*', array(), __METHOD__, array( 'LIMIT' => self::$mChangeLimit, 'ORDER BY' => 'rc_timestamp asc' ) );
-
-		$counter = 1;
-
-		while ( $row = $dbr->fetchObject( $res ) ) {
-			$vars = AbuseFilter::getVarsFromRCRow( $row );
-
-			if (!$vars)
-				continue;
-
-			$result = AbuseFilter::checkConditions( $this->mFilter, $vars );
-
-			if ($result || $this->mShowNegative) {
-				$rc = RecentChange::newFromRow( $row );
-				$rc->counter = $counter++;
-				$output .= $changesList->recentChangesLine( $rc, false );
-			}
-		}
-
-		$output .= $changesList->endRecentChangesList();
-
-		$wgOut->addHTML( $output );
-	}
-
-	function loadParameters() {
-		global $wgRequest;
-
-		$this->mFilter = $wgRequest->getText( 'wpTestFilter' );
-		$this->mShowNegative = $wgRequest->getBool( 'wpShowNegative' );
-	}
-}
\ No newline at end of file
Index: trunk/extensions/AbuseFilter/Views/examine.js
===================================================================
--- trunk/extensions/AbuseFilter/Views/examine.js	(revision 0)
+++ trunk/extensions/AbuseFilter/Views/examine.js	(revision 46557)
@@ -0,0 +1,25 @@
+/** Scripts for Examiner */
+
+function examinerCheckFilter() {
+	var filter = document.getElementById( 'wpTestFilter' ).value;
+
+	sajax_do_call( 'AbuseFilter::ajaxCheckFilterWithVars', [filter, wgExamineVars], function(request) {
+		var response = request.responseText;
+		var el = document.getElementById( 'mw-abusefilter-syntaxresult' );
+
+		el.style.display = 'block';
+
+		if (response == 'MATCH') {
+			changeText( el, wgMessageMatch );
+		} else if (response == 'NOMATCH') {
+			changeText( el, wgMessageNomatch );
+		} else if (response == 'SYNTAXERROR' ) {
+			changeText( el, wgMessageError );
+		}
+	} );
+}
+
+addOnloadHook( function() {
+	var el = document.getElementById( 'mw-abusefilter-examine-test' );
+	addHandler( el, 'click', examinerCheckFilter );
+} );
\ No newline at end of file
Index: trunk/extensions/AbuseFilter/Views/AbuseFilterViewList.php
===================================================================
--- trunk/extensions/AbuseFilter/Views/AbuseFilterViewList.php	(revision 46556)
+++ trunk/extensions/AbuseFilter/Views/AbuseFilterViewList.php	(revision 46557)
@@ -14,13 +14,14 @@
 
 		// Quick links
 		$wgOut->addWikiMsg( 'abusefilter-links' );
-		$lists = array( 'tools', 'test' );
+		$lists = array( 'tools', 'test', 'examine' );
 		if ($this->canEdit())
 			$lists[] = 'new';
 		$links = '';
 		$sk = $wgUser->getSkin();
 		foreach( $lists as $list ) {
 			$title = $this->getTitle( $list );
+			$list = strtr( $list, '/', '-' );
 
 			$link = $sk->link( $title, wfMsg( "abusefilter-$list" ) );
 			$links .= Xml::tags( 'li', null, $link ) . "\n";
Index: trunk/extensions/AbuseFilter/Views/AbuseFilterView.php
===================================================================
--- trunk/extensions/AbuseFilter/Views/AbuseFilterView.php	(revision 46556)
+++ trunk/extensions/AbuseFilter/Views/AbuseFilterView.php	(revision 46557)
@@ -25,4 +25,16 @@
 
 		return $canEdit;
 	}
+}
+
+class AbuseFilterChangesList extends OldChangesList {
+	protected function insertExtra( &$s, &$rc, &$classes ) {
+		## Empty, used for subclassers to add anything special.
+		$sk = $this->skin;
+
+		$title = SpecialPage::getTitleFor( 'AbuseFilter', "examine/".$rc->mAttribs['rc_id'] );
+		$examineLink = $sk->link( $title, wfMsgExt( 'abusefilter-changeslist-examine', 'parseinline' ) );
+
+		$s .= " ($examineLink)";
+	}
 }
\ No newline at end of file
Index: trunk/extensions/AbuseFilter/Views/AbuseFilterViewTestBatch.php
===================================================================
--- trunk/extensions/AbuseFilter/Views/AbuseFilterViewTestBatch.php	(revision 0)
+++ trunk/extensions/AbuseFilter/Views/AbuseFilterViewTestBatch.php	(revision 46557)
@@ -0,0 +1,103 @@
+<?php
+
+if (!defined( 'MEDIAWIKI' ))
+	die();
+
+class AbuseFilterViewTestBatch extends AbuseFilterView {
+	// Hard-coded for now.
+	static $mChangeLimit = 100;
+	
+	function show( ) {
+		global $wgOut, $wgUser, $wgRequest;
+		
+		AbuseFilter::disableConditionLimit();
+
+		$this->loadParameters();
+		
+		$wgOut->setPageTitle( wfMsg( 'abusefilter-test' ) );
+		$wgOut->addWikiMsg( 'abusefilter-test-intro', self::$mChangeLimit );
+
+		$output = '';
+		$output .= AbuseFilter::buildEditBox( $this->mFilter, 'wpTestFilter' ) . "\n";
+		$output .= Xml::inputLabel( wfMsg( 'abusefilter-test-load-filter' ), 'wpInsertFilter', 'mw-abusefilter-load-filter', 10, '' ) . '&nbsp;' .
+			Xml::element( 'input', array( 'type' => 'button', 'value' => wfMsg( 'abusefilter-test-load' ), 'id' => 'mw-abusefilter-load' ) );
+		$output = Xml::tags( 'div', array( 'id' => 'mw-abusefilter-test-editor' ), $output );
+
+		// Removed until I can distinguish between positives and negatives :)
+// 		$output .= Xml::tags( 'p', null, Xml::checkLabel( wfMsg( 'abusefilter-test-shownegative' ), 'wpShowNegative', 'wpShowNegative', $this->mShowNegative ) );
+
+		// Selectory stuff
+		$selectFields = array();
+		$selectFields['abusefilter-test-user'] = wfInput( 'wpTestUser', 45, $this->mTestUser );
+		$selectFields['abusefilter-test-period-start'] = wfInput( 'wpTestPeriodStart', 45, $this->mTestPeriodStart );
+		$selectFields['abusefilter-test-period-end'] = wfInput( 'wpTestPeriodEnd', 45, $this->mTestPeriodEnd );
+		$output .= Xml::buildForm( $selectFields, 'abusefilter-test-submit' );
+		
+		$output .= Xml::hidden( 'title', $this->getTitle("test")->getPrefixedText() );
+		$output = Xml::tags( 'form', array( 'action' => $this->getTitle("test")->getLocalURL(), 'method' => 'POST' ), $output );
+
+		$output = Xml::fieldset( wfMsg( 'abusefilter-test-legend' ), $output );
+
+		$wgOut->addHTML( $output );
+
+		if ($wgRequest->wasPosted()) {
+			$this->doTest();
+		}
+	}
+
+	function doTest() {
+		// Quick syntax check.
+		global $wgUser, $wgOut;
+		if ( ($result = AbuseFilter::checkSyntax( $this->mFilter )) !== true ) {
+			$wgOut->addWikiMsg( 'abusefilter-test-syntaxerr' );
+			return;
+		}
+		$dbr = wfGetDB( DB_SLAVE );
+
+		$conds = array( 'rc_user_text' => $this->mTestUser );
+
+		if ($this->mTestPeriodStart) {
+			$conds[] = 'rc_timestamp>='.$dbr->addQuotes( $dbr->timestamp( strtotime( $this->mTestPeriodStart ) ) );
+		}
+		if ($this->mTestPeriodEnd) {
+			$conds[] = 'rc_timestamp<='.$dbr->addQuotes( $dbr->timestamp( strtotime( $this->mTestPeriodEnd ) ) );
+		}
+
+		// Get our ChangesList
+		$changesList = new AbuseFilterChangesList( $wgUser->getSkin() );
+		$output = $changesList->beginRecentChangesList();
+
+		$res = $dbr->select( 'recentchanges', '*', array_filter( $conds ), __METHOD__, array( 'LIMIT' => self::$mChangeLimit, 'ORDER BY' => 'rc_timestamp desc' ) );
+
+		$counter = 1;
+
+		while ( $row = $dbr->fetchObject( $res ) ) {
+			$vars = AbuseFilter::getVarsFromRCRow( $row );
+
+			if (!$vars)
+				continue;
+
+			$result = AbuseFilter::checkConditions( $this->mFilter, $vars );
+
+			if ($result || $this->mShowNegative) {
+				$rc = RecentChange::newFromRow( $row );
+				$rc->counter = $counter++;
+				$output .= $changesList->recentChangesLine( $rc, false );
+			}
+		}
+
+		$output .= $changesList->endRecentChangesList();
+
+		$wgOut->addHTML( $output );
+	}
+
+	function loadParameters() {
+		global $wgRequest;
+
+		$this->mFilter = $wgRequest->getText( 'wpTestFilter' );
+		$this->mShowNegative = $wgRequest->getBool( 'wpShowNegative' );
+		$this->mTestUser = $wgRequest->getText( 'wpTestUser' );
+		$this->mTestPeriodEnd = $wgRequest->getText( 'wpTestPeriodEnd' );
+		$this->mTestPeriodStart = $wgRequest->getText( 'wpTestPeriodStart' );
+	}
+}
Index: trunk/extensions/AbuseFilter/Views/AbuseFilterViewExamine.php
===================================================================
--- trunk/extensions/AbuseFilter/Views/AbuseFilterViewExamine.php	(revision 0)
+++ trunk/extensions/AbuseFilter/Views/AbuseFilterViewExamine.php	(revision 46557)
@@ -0,0 +1,134 @@
+<?php
+
+if (!defined( 'MEDIAWIKI' ))
+	die();
+
+class AbuseFilterViewExamine extends AbuseFilterView {
+
+	function show( ) {
+		global $wgOut, $wgUser;
+
+		$wgOut->setPageTitle( wfMsg( 'abusefilter-examine' ) );
+		$wgOut->addWikiMsg( 'abusefilter-examine-intro' );
+
+		$this->loadParameters();
+
+		// Check if we've got a subpage
+		if ( count($this->mParams)>1 && is_numeric($this->mParams[1]) ) {
+			$this->showExaminer( $this->mParams[1] );
+		} else {
+			$this->showSearch();
+		}
+	}
+
+	function showSearch() {
+		global $wgUser, $wgOut;
+		
+		// Add selector
+		$selector = '';
+
+		$selectFields = array(); ## Same fields as in Test
+		$selectFields['abusefilter-test-user'] = wfInput( 'wpSearchUser', 45, $this->mSearchUser );
+		$selectFields['abusefilter-test-period-start'] = wfInput( 'wpSearchPeriodStart', 45, $this->mSearchPeriodStart );
+		$selectFields['abusefilter-test-period-end'] = wfInput( 'wpSearchPeriodEnd', 45, $this->mSearchPeriodEnd );
+
+		$selector .= Xml::buildForm( $selectFields, 'abusefilter-examine-submit' );
+		$selector .= Xml::hidden( 'submit', 1 );
+		$selector .= Xml::hidden( 'title', $this->getTitle( 'examine' )->getPrefixedText() );
+		$selector = Xml::tags( 'form', array( 'action' => $this->getTitle( 'examine' )->getLocalURL(), 'method' => 'GET' ), $selector );
+		$selector = Xml::fieldset( wfMsg( 'abusefilter-examine-legend' ), $selector );
+		$wgOut->addHTML( $selector );
+
+		if ($this->mSubmit) {
+			$this->showResults();
+		}
+	}
+
+	function showResults() {
+		global $wgUser, $wgOut;
+		
+		$dbr = wfGetDB( DB_SLAVE );
+
+		$conds = array( 'rc_user_text' => $this->mSearchUser );
+		if ( $startTS = strtotime($this->mSearchPeriodStart) ) {
+			$conds[] = 'rc_timestamp>=' . $dbr->addQuotes( $dbr->timestamp( $startTS ) );
+		}
+		if ( $endTS = strtotime($this->mSearchPeriodEnd) ) {
+			$conds[] = 'rc_timestamp<=' . $dbr->addQuotes( $dbr->timestamp( $endTS ) );
+		}
+		
+		$res = $dbr->select( 'recentchanges', '*', array_filter($conds), __METHOD__, array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => '500' ) );
+
+		$changesList = new AbuseFilterChangesList( $wgUser->getSkin() );
+		$output = $changesList->beginRecentChangesList();
+		$counter = 1;
+
+		while ( $row = $dbr->fetchObject( $res ) ) {
+			$rc = RecentChange::newFromRow( $row );
+			$rc->counter = $counter++;
+			$output .= $changesList->recentChangesLine( $rc, false );
+		}
+
+		$output .= $changesList->endRecentChangesList();
+
+		$wgOut->addHTML( $output );
+	}
+
+	function showExaminer( $rcid ) {
+		global $wgOut, $wgUser;
+		
+		// Get data
+		$dbr = wfGetDB( DB_SLAVE );
+		$row = $dbr->selectRow( 'recentchanges', '*', array( 'rc_id' => $rcid ), __METHOD__ );
+
+		if (!$row) {
+			$wgOut->addWikiMsg( 'abusefilter-examine-notfound' );
+			return;
+		}
+
+		$vars = AbuseFilter::getVarsFromRCRow( $row );
+
+		if (!$vars) {
+			$wgOut->addWikiMsg( 'abusefilter-examine-incompatible' );
+			return;
+		}
+
+		$output = '';
+
+		// Send armoured as JSON -- I totally give up on trying to send it as a proper object.
+		$wgOut->addInlineScript( "var wgExamineVars = ". Xml::encodeJsVar( json_encode( $vars ) ) .";" );
+		$wgOut->addInlineScript( file_get_contents( dirname( __FILE__ ) . "/examine.js" ) );
+
+		// Add messages
+		$msg = array();
+		$msg['match'] = wfMsg( 'abusefilter-examine-match' );
+		$msg['nomatch'] = wfMsg( 'abusefilter-examine-nomatch' );
+		$msg['syntaxerror'] = wfMsg( 'abusefilter-examine-syntaxerror' );
+		$wgOut->addInlineScript( "var wgMessageMatch = ".Xml::encodeJsVar( $msg['match'] ) . ";\n".
+					"var wgMessageNomatch = ".Xml::encodeJsVar( $msg['nomatch'] ) . ";\n".
+					"var wgMessageError = ".Xml::encodeJsVar( $msg['syntaxerror'] ) . ";\n" );
+
+		// Add test bit
+		$tester = Xml::tags( 'h2', null, wfMsgExt( 'abusefilter-examine-test', 'parseinline' ) );
+		$tester .= AbuseFilter::buildEditBox( '', 'wpTestFilter', false );
+		$tester .= "\n" . Xml::inputLabel( wfMsg( 'abusefilter-test-load-filter' ), 'wpInsertFilter', 'mw-abusefilter-load-filter', 10, '' ) . '&nbsp;' .
+			Xml::element( 'input', array( 'type' => 'button', 'value' => wfMsg( 'abusefilter-test-load' ), 'id' => 'mw-abusefilter-load' ) );
+		$output .= Xml::tags( 'div', array( 'id' => 'mw-abusefilter-examine-editor' ), $tester );
+		$output .= Xml::tags( 'p', null, Xml::element( 'input', array( 'type' => 'button', 'value' => wfMsg( 'abusefilter-examine-test-button' ), 'id' => 'mw-abusefilter-examine-test' ) ) .
+				Xml::element( 'div', array( 'id' => 'mw-abusefilter-syntaxresult', 'style' => 'display: none;' ), '&nbsp;' ) );
+
+		// Variable dump
+		$output .= Xml::tags( 'h2', null, wfMsgExt( 'abusefilter-examine-vars', 'parseinline' ) );
+		$output .= AbuseFilter::buildVarDumpTable( $vars );
+
+		$wgOut->addHTML( $output );
+	}
+
+	function loadParameters() {
+		global $wgRequest;
+		$this->mSearchUser = $wgRequest->getText( 'wpSearchUser' );
+		$this->mSearchPeriodStart = $wgRequest->getText( 'wpSearchPeriodStart' );
+		$this->mSearchPeriodEnd = $wgRequest->getText( 'wpSearchPeriodEnd' );
+		$this->mSubmit = $wgRequest->getCheck( 'submit' );
+	}
+}
\ No newline at end of file
Index: trunk/extensions/AbuseFilter/AbuseFilter.class.php
===================================================================
--- trunk/extensions/AbuseFilter/AbuseFilter.class.php	(revision 46556)
+++ trunk/extensions/AbuseFilter/AbuseFilter.class.php	(revision 46557)
@@ -68,6 +68,25 @@
 		return strval($row->af_pattern);
 	}
 
+	public static function ajaxCheckFilterWithVars( $filter, $vars ) {
+		global $wgUser;
+
+		// Anti-DoS
+		if ( !$wgUser->isAllowed( 'abusefilter-view' ) ) {
+			return false;
+		}
+
+		// If we have a syntax error.
+		if ( self::checkSyntax( $filter ) !== true ) {
+			return 'SYNTAXERROR';
+		}
+		
+		$vars = json_decode( $vars, true );
+		$result = self::checkConditions( $filter, $vars );
+
+		return $result ? 'MATCH' : 'NOMATCH';
+	}
+
 	public static function triggerLimiter( $val = 1 ) {
 		self::$condCount += $val;
 
@@ -669,7 +688,7 @@
 		return $user;
 	}
 
-	static function buildEditBox( $rules, $textName = 'wpFilterRules' ) {
+	static function buildEditBox( $rules, $textName = 'wpFilterRules', $addResultDiv = true ) {
 		global $wgOut;
 
 		$rules = Xml::textarea( $textName, ( isset( $rules ) ? $rules."\n" : "\n" ) );
@@ -695,8 +714,10 @@
 
 		// Add syntax checking
 		$rules .= Xml::element( 'input', array( 'type' => 'button', 'onclick' => 'doSyntaxCheck()', 'value' => wfMsg( 'abusefilter-edit-check' ), 'id' => 'mw-abusefilter-syntaxcheck' ) );
-		$rules .= Xml::element( 'div', array( 'id' => 'mw-abusefilter-syntaxresult', 'style' => 'display: none;' ), '&nbsp;' );
 
+		if ($addResultDiv)
+			$rules .= Xml::element( 'div', array( 'id' => 'mw-abusefilter-syntaxresult', 'style' => 'display: none;' ), '&nbsp;' );
+
 		// Add script
 		$editScript = file_get_contents(dirname(__FILE__)."/edit.js");
 		$editScript = "var wgFilterBoxName = ".Xml::encodeJSVar( $textName ).";\n$editScript";
@@ -882,4 +903,36 @@
 
 		return $vars;
 	}
+
+	public static function buildVarDumpTable( $vars ) {
+		$output = '';
+
+		// I don't want to change the names of the pre-existing messages
+		// describing the variables, nor do I want to rewrite them, so I'm just
+		// mapping the variable names to builder messages with a pre-existing array.
+		$variableMessageMappings = self::$builderValues['vars'];
+		
+		$output .= Xml::openElement( 'table', array( 'class' => 'mw-abuselog-details' ) ) . Xml::openElement( 'tbody' );
+
+		$header = Xml::element( 'th', null, wfMsg( 'abusefilter-log-details-var' ) ) . Xml::element( 'th', null, wfMsg( 'abusefilter-log-details-val' ) );
+		$output .= Xml::tags( 'tr', null, $header );
+
+		// Now, build the body of the table.
+		foreach( $vars as $key => $value ) {
+			if ( !empty($variableMessageMappings[$key]) ) {
+				$mapping = $variableMessageMappings[$key];
+				$keyDisplay = wfMsgExt( "abusefilter-edit-builder-vars-$mapping", 'parseinline' ) . ' (' . Xml::element( 'tt', null, $key ) . ')';
+			} else {
+				$keyDisplay = Xml::element( 'tt', null, $key );
+			}
+
+			$value = Xml::element( 'div', array( 'class' => 'mw-abuselog-var-value' ), $value );
+
+			$trow = Xml::tags( 'td', array( 'class' => 'mw-abuselog-var' ), $keyDisplay ) . Xml::tags( 'td', array( 'class' => 'mw-abuselog-var-value' ), $value );
+			$output .= Xml::tags( 'tr', array( 'class' => "mw-abuselog-details-$key mw-abuselog-value" ), $trow );
+		}
+
+		$output .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
+		return $output;
+	}
 }
Index: trunk/extensions/AbuseFilter/AbuseFilter.i18n.php
===================================================================
--- trunk/extensions/AbuseFilter/AbuseFilter.i18n.php	(revision 46556)
+++ trunk/extensions/AbuseFilter/AbuseFilter.i18n.php	(revision 46557)
@@ -316,6 +316,7 @@
 Reason given: $2',
 	'abusefilter-revert-reasonfield' => 'Reason for revert:',
 
+	// These messages are for batch checking
 	'abusefilter-test' => 'Test a filter against previous edits',
 	'abusefilter-test-intro' => 'This page allows you to check a filter entered in the box below against the last $1 changes.
 To load an existing filter, type its filter ID into the box below the edit textbox, and click the "Load" button.',
@@ -323,6 +324,25 @@
 	'abusefilter-test-load-filter' => 'Load filter ID:',
 	'abusefilter-test-submit' => 'Test',
 	'abusefilter-test-load' => 'Load',
+	'abusefilter-test-user' => 'Changes by user:',
+	'abusefilter-test-period-start' => 'Changes made after:',
+	'abusefilter-test-period-end' => 'Changes made before:',
+	'abusefilter-changeslist-examine' => 'examine',
+
+	// And these messages are for examining specific actions.
+	'abusefilter-examine' => 'Examine individual changes',
+	'abusefilter-examine-intro' => 'This page allows you to examine the variables generated by the Abuse Filter for an individual change, and test it against filters.',
+	'abusefilter-examine-legend' => 'Select changes',
+	'abusefilter-examine-diff' => 'Diff URL:',
+	'abusefilter-examine-user' => 'User:',
+	'abusefilter-examine-title' => 'Page title:',
+	'abusefilter-examine-submit' => 'Search',
+	'abusefilter-examine-vars' => 'Variables generated for this change',
+	'abusefilter-examine-test' => 'Test this change against a filter',
+	'abusefilter-examine-test-button' => 'Test filter',
+	'abusefilter-examine-match' => 'The filter matched this change.',
+	'abusefilter-examine-nomatch' => 'The filter did not match this change.',
+	'abusefilter-examine-syntaxerror' => 'The filter has invalid syntax',
 );
 
 /** Message documentation (Message documentation)

Follow-up revisions

Rev.Commit summaryAuthorDate
r46560Minor fixes for r46557...werdna23:04, 29 January 2009
r46564Add a few missing messages, and fix a syntax error from r46557.werdna23:36, 29 January 2009

Status & tagging log

  • 00:05, 6 February 2009 Werdna (Talk | contribs) changed the status of r46557 [removed: new added: deferred]
Personal tools
Namespaces
Variants
Views
Actions
Site
Support
Download
Development
Communication
Toolbox