mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter.git
synced 2024-09-24 02:38:16 +00:00
Bold and apply a subtle background colour to the changed fields in Abuse Filter history -- will make things much easier to track.
This commit is contained in:
parent
83cb0e5322
commit
83d4b5a91f
|
@ -11,6 +11,7 @@ class AbuseFilter {
|
|||
public static $condCount = 0;
|
||||
public static $filters = array();
|
||||
public static $tagsToSet = array();
|
||||
public static $history_mappings = array( 'af_pattern' => 'afh_pattern', 'af_user' => 'afh_user', 'af_user_text' => 'afh_user_text', 'af_timestamp' => 'afh_timestamp', 'af_comments' => 'afh_comments', 'af_public_comments' => 'afh_public_comments', 'af_deleted' => 'afh_deleted', 'af_id' => 'afh_filter' );
|
||||
|
||||
public static function generateUserVars( $user ) {
|
||||
$vars = array();
|
||||
|
@ -675,4 +676,69 @@ class AbuseFilter {
|
|||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/** Each version is expected to be an array( $row, $actions )
|
||||
Returns an array of fields that are different.*/
|
||||
static function compareVersions( $version_1, $version_2 ) {
|
||||
$compareFields = array( 'af_public_comments', 'af_pattern', 'af_comments', 'af_deleted', 'af_enabled', 'af_hidden' );
|
||||
$differences = array();
|
||||
|
||||
list($row1, $actions1) = $version_1;
|
||||
list($row2, $actions2) = $version_2;
|
||||
|
||||
foreach( $compareFields as $field ) {
|
||||
if ($row1->$field != $row2->$field) {
|
||||
$differences[] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
global $wgAbuseFilterAvailableActions;
|
||||
foreach( $wgAbuseFilterAvailableActions as $action ) {
|
||||
if ( !isset($actions1[$action]) && !isset( $actions2[$action] ) ) {
|
||||
// They're both unset
|
||||
} elseif ( isset($actions1[$action]) && isset( $actions2[$action] ) ) {
|
||||
// They're both set.
|
||||
if ( array_diff( $actions1[$action]['parameters'], $actions2[$action]['parameters'] ) ) {
|
||||
// Different parameters
|
||||
$differences[] = 'actions';
|
||||
}
|
||||
} else {
|
||||
// One's unset, one's set.
|
||||
$differences[] = 'actions';
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique( $differences );
|
||||
}
|
||||
|
||||
static function translateFromHistory( $row ) {
|
||||
## Translate into an abuse_filter row with some black magic. This is ever so slightly evil!
|
||||
$af_row = new StdClass;
|
||||
|
||||
foreach (self::$history_mappings as $af_col => $afh_col ) {
|
||||
$af_row->$af_col = $row->$afh_col;
|
||||
}
|
||||
|
||||
## Process flags
|
||||
|
||||
$af_row->af_deleted = 0;
|
||||
$af_row->af_hidden = 0;
|
||||
$af_row->af_enabled = 0;
|
||||
|
||||
$flags = explode(',', $row->afh_flags );
|
||||
foreach( $flags as $flag ) {
|
||||
$col_name = "af_$flag";
|
||||
$af_row->$col_name = 1;
|
||||
}
|
||||
|
||||
## Process actions
|
||||
$actions_raw = unserialize($row->afh_actions);
|
||||
$actions_output = array();
|
||||
|
||||
foreach( $actions_raw as $action => $parameters ) {
|
||||
$actions_output[$action] = array( 'action' => $action, 'parameters' => $parameters );
|
||||
}
|
||||
|
||||
return array( $af_row, $actions_output );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,8 +237,8 @@ A brief description of the abuse rule which your action matched is: $1",
|
|||
'abusefilter-filter-log' => 'Recent filter changes',
|
||||
'abusefilter-history' => 'History for filter $1',
|
||||
'abusefilter-history-foruser' => 'Changes by $1',
|
||||
'abusefilter-history-hidden' => 'hidden',
|
||||
'abusefilter-history-enabled' => 'enabled',
|
||||
'abusefilter-history-hidden' => 'Hidden',
|
||||
'abusefilter-history-enabled' => 'Enabled',
|
||||
'abusefilter-history-timestamp' => 'Time',
|
||||
'abusefilter-history-user' => 'User',
|
||||
'abusefilter-history-public' => 'Public filter description',
|
||||
|
|
|
@ -24,6 +24,9 @@ class SpecialAbuseFilter extends SpecialPage {
|
|||
$wgOut->setRobotPolicy( "noindex,nofollow" );
|
||||
$wgOut->setArticleRelated( false );
|
||||
$wgOut->enableClientCache( false );
|
||||
|
||||
global $wgScriptPath;
|
||||
$wgOut->addExtensionStyle( $wgScriptPath."/extensions/AbuseFilter/abusefilter.css" );
|
||||
|
||||
// Are we allowed?
|
||||
if ( !$wgUser->isAllowed( 'abusefilter-view' ) ) {
|
||||
|
|
|
@ -5,8 +5,6 @@ if (!defined( 'MEDIAWIKI' ))
|
|||
|
||||
class AbuseFilterViewEdit extends AbuseFilterView {
|
||||
|
||||
static $history_mappings = array( 'af_pattern' => 'afh_pattern', 'af_user' => 'afh_user', 'af_user_text' => 'afh_user_text', 'af_timestamp' => 'afh_timestamp', 'af_comments' => 'afh_comments', 'af_public_comments' => 'afh_public_comments', 'af_deleted' => 'afh_deleted', 'af_id' => 'afh_filter' );
|
||||
|
||||
function __construct( $page, $params ) {
|
||||
parent::__construct( $page, $params );
|
||||
$this->mFilter = $page->mFilter;
|
||||
|
@ -34,7 +32,10 @@ class AbuseFilterViewEdit extends AbuseFilterView {
|
|||
|
||||
list ($newRow, $actions) = $this->loadRequest($filter);
|
||||
|
||||
$differences = $this->compareVersions( array($newRow, $actions), array( $newRow->mOriginalRow, $newRow->mOriginalActions ) );
|
||||
$differences = AbuseFilter::compareVersions( array($newRow, $actions), array( $newRow->mOriginalRow, $newRow->mOriginalActions ) );
|
||||
|
||||
unset( $newRow->mOriginalRow );
|
||||
unset( $newRow->mOriginalActions );
|
||||
|
||||
if (!count($differences)) {
|
||||
$wgOut->redirect( $this->getTitle()->getLocalURL() );
|
||||
|
@ -90,7 +91,7 @@ class AbuseFilterViewEdit extends AbuseFilterView {
|
|||
// Create a history row
|
||||
$afh_row = array();
|
||||
|
||||
foreach( self::$history_mappings as $af_col => $afh_col ) {
|
||||
foreach( AbuseFilter::$history_mappings as $af_col => $afh_col ) {
|
||||
$afh_row[$afh_col] = $newRow[$af_col];
|
||||
}
|
||||
|
||||
|
@ -101,6 +102,8 @@ class AbuseFilterViewEdit extends AbuseFilterView {
|
|||
}
|
||||
$afh_row['afh_actions'] = serialize($displayActions);
|
||||
|
||||
$afh_row['afh_changed_fields'] = implode( ',', $differences );
|
||||
|
||||
// Flags
|
||||
$flags = array();
|
||||
if ($newRow['af_hidden'])
|
||||
|
@ -367,40 +370,6 @@ class AbuseFilterViewEdit extends AbuseFilterView {
|
|||
return array( $row, $actions );
|
||||
}
|
||||
|
||||
/** Each version is expected to be an array( $row, $actions )
|
||||
Returns an array of fields that are different.*/
|
||||
function compareVersions( $version_1, $version_2 ) {
|
||||
$compareFields = array( 'af_public_comments', 'af_pattern', 'af_comments', 'af_deleted', 'af_enabled', 'af_hidden' );
|
||||
$differences = array();
|
||||
|
||||
list($row1, $actions1) = $version_1;
|
||||
list($row2, $actions2) = $version_2;
|
||||
|
||||
foreach( $compareFields as $field ) {
|
||||
if ($row1->$field != $row2->$field) {
|
||||
$differences[] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
global $wgAbuseFilterAvailableActions;
|
||||
foreach( $wgAbuseFilterAvailableActions as $action ) {
|
||||
if ( !isset($actions1[$action]) && !isset( $actions2[$action] ) ) {
|
||||
// They're both unset
|
||||
} elseif ( isset($actions1[$action]) && isset( $actions2[$action] ) ) {
|
||||
// They're both set.
|
||||
if ( array_diff( $actions1[$action]['parameters'], $actions2[$action]['parameters'] ) ) {
|
||||
// Different parameters
|
||||
$differences[] = 'actions';
|
||||
}
|
||||
} else {
|
||||
// One's unset, one's set.
|
||||
$differences[] = 'actions';
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique( $differences );
|
||||
}
|
||||
|
||||
function loadRequest( $filter, $history_id = null ) {
|
||||
static $row = null;
|
||||
static $actions = null;
|
||||
|
@ -471,34 +440,6 @@ class AbuseFilterViewEdit extends AbuseFilterView {
|
|||
// Load the row.
|
||||
$row = $dbr->selectRow( 'abuse_filter_history', '*', array( 'afh_id' => $id ), __METHOD__ );
|
||||
|
||||
## Translate into an abuse_filter row with some black magic. This is ever so slightly evil!
|
||||
$af_row = new StdClass;
|
||||
|
||||
foreach (self::$history_mappings as $af_col => $afh_col ) {
|
||||
$af_row->$af_col = $row->$afh_col;
|
||||
}
|
||||
|
||||
## Process flags
|
||||
|
||||
$af_row->af_deleted = 0;
|
||||
$af_row->af_hidden = 0;
|
||||
$af_row->af_enabled = 0;
|
||||
|
||||
$flags = explode(',', $row->afh_flags );
|
||||
foreach( $flags as $flag ) {
|
||||
$col_name = "af_$flag";
|
||||
$af_row->$col_name = 1;
|
||||
}
|
||||
|
||||
## Process actions
|
||||
$actions_raw = unserialize($row->afh_actions);
|
||||
$actions_output = array();
|
||||
|
||||
foreach( $actions_raw as $action => $parameters ) {
|
||||
$actions_output[$action] = array( 'action' => $action, 'parameters' => $parameters );
|
||||
}
|
||||
|
||||
|
||||
return array( $af_row, $actions_output );
|
||||
return AbuseFilter::translateFromHistory( $row );
|
||||
}
|
||||
}
|
|
@ -80,6 +80,7 @@ class AbuseFilterHistoryPager extends TablePager {
|
|||
if (!$this->mFilter) {
|
||||
// awful hack
|
||||
$headers = array( 'afh_filter' => 'abusefilter-history-filterid' ) + $headers;
|
||||
unset( $headers['afh_pattern'] );
|
||||
}
|
||||
|
||||
$headers = array_map( 'wfMsg', $headers );
|
||||
|
@ -99,25 +100,33 @@ class AbuseFilterHistoryPager extends TablePager {
|
|||
|
||||
$row = $this->mCurrentRow;
|
||||
|
||||
$formatted = '';
|
||||
|
||||
switch($name) {
|
||||
case 'afh_timestamp':
|
||||
$title = SpecialPage::getTitleFor( 'AbuseFilter', 'history/'.$this->mFilter.'/item/'.$row->afh_id );
|
||||
return $sk->link( $title, $wgLang->timeanddate( $row->afh_timestamp ) );
|
||||
$formatted = $sk->link( $title, $wgLang->timeanddate( $row->afh_timestamp ) );
|
||||
break;
|
||||
case 'afh_user_text':
|
||||
return $sk->userLink( $row->afh_user, $row->afh_user_text ) . ' ' . $sk->userToolLinks( $row->afh_user, $row->afh_user_text );
|
||||
$formatted = $sk->userLink( $row->afh_user, $row->afh_user_text ) . ' ' . $sk->userToolLinks( $row->afh_user, $row->afh_user_text );
|
||||
break;
|
||||
case 'afh_public_comments':
|
||||
return $wgOut->parse( $value );
|
||||
$formatted = $wgOut->parse( $value );
|
||||
break;
|
||||
case 'afh_flags':
|
||||
$flags = array_filter( explode( ',', $value ) );
|
||||
$flags_display = array();
|
||||
foreach( $flags as $flag ) {
|
||||
$flags_display[] = wfMsg( "abusefilter-history-$flag" );
|
||||
}
|
||||
return implode( ', ', $flags_display );
|
||||
$formatted = implode( ', ', $flags_display );
|
||||
break;
|
||||
case 'afh_pattern':
|
||||
return htmlspecialchars( $wgLang->truncate( $value, 200, '...' ) );
|
||||
$formatted = htmlspecialchars( $wgLang->truncate( $value, 200, '...' ) );
|
||||
break;
|
||||
case 'afh_comments':
|
||||
return htmlspecialchars( $wgLang->truncate( $value, 200, '...' ) );
|
||||
$formatted = htmlspecialchars( $wgLang->truncate( $value, 200, '...' ) );
|
||||
break;
|
||||
case 'afh_actions':
|
||||
$actions = unserialize( $value );
|
||||
|
||||
|
@ -128,21 +137,42 @@ class AbuseFilterHistoryPager extends TablePager {
|
|||
}
|
||||
$display_actions = Xml::tags( 'ul', null, $display_actions );
|
||||
|
||||
return $display_actions;
|
||||
$formatted = $display_actions;
|
||||
break;
|
||||
case 'afh_filter':
|
||||
$title = $this->getTitle( $value );
|
||||
return $sk->link( $title, $value );
|
||||
$title = $this->mPage->getTitle( strval($value) );
|
||||
$formatted = $sk->link( $title, $value );
|
||||
break;
|
||||
default:
|
||||
$formatted = "Unable to format $name";
|
||||
break;
|
||||
}
|
||||
|
||||
return "Unable to format name $name\n";
|
||||
$mappings = array_flip(AbuseFilter::$history_mappings) + array( 'afh_actions' => 'actions' );
|
||||
$changed = explode( ',', $row->afh_changed_fields );
|
||||
|
||||
$fieldChanged = false;
|
||||
if ($name == 'afh_flags') {
|
||||
// This is a bit freaky, but it works. Basically, returns true if any of those filters are in the $changed array.
|
||||
if ( count( array_diff( array( 'af_enabled', 'af_hidden', 'af_deleted' ), $changed ) ) < 3 ) {
|
||||
$fieldChanged = true;
|
||||
}
|
||||
} elseif ( in_array( $mappings[$name], $changed ) ) {
|
||||
$fieldChanged = true;
|
||||
}
|
||||
|
||||
if ($fieldChanged)
|
||||
$formatted = Xml::tags( 'strong', array( 'class' => 'mw-abusefilter-history-changed' ), $formatted );
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
function getQueryInfo() {
|
||||
$info = array(
|
||||
'tables' => 'abuse_filter_history',
|
||||
'fields' => $this->mFilter ?
|
||||
array( 'afh_timestamp', 'afh_user_text', 'afh_public_comments', 'afh_flags', 'afh_pattern', 'afh_comments', 'afh_actions', 'afh_id', 'afh_user' ) :
|
||||
array( 'afh_filter', 'afh_timestamp', 'afh_user_text', 'afh_public_comments', 'afh_flags', 'afh_comments', 'afh_actions', 'afh_id', 'afh_user' ),
|
||||
array( 'afh_timestamp', 'afh_user_text', 'afh_public_comments', 'afh_flags', 'afh_pattern', 'afh_comments', 'afh_actions', 'afh_id', 'afh_user', 'afh_changed_fields' ) :
|
||||
array( 'afh_filter', 'afh_timestamp', 'afh_user_text', 'afh_public_comments', 'afh_flags', 'afh_comments', 'afh_actions', 'afh_id', 'afh_user', 'afh_changed_fields'),
|
||||
'conds' => $this->mFilter ? array( 'afh_filter' => $this->mFilter ) : array(),
|
||||
);
|
||||
|
||||
|
|
|
@ -18,4 +18,8 @@ table.mw-abuselog-details th {
|
|||
|
||||
table.mw-abuselog-details caption {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mw-abusefilter-history-changed {
|
||||
background: #ffe0e0;
|
||||
}
|
|
@ -60,6 +60,7 @@ CREATE TABLE /*$wgDBprefix*/abuse_filter_history (
|
|||
afh_public_comments TINYBLOB,
|
||||
afh_actions BLOB,
|
||||
afh_deleted tinyint(1) NOT NULL DEFAULT 0,
|
||||
afh_changed_fields varchar(255) NOT NULL DEFAULT '',
|
||||
|
||||
PRIMARY KEY (afh_id),
|
||||
KEY (afh_filter),
|
||||
|
|
Loading…
Reference in a new issue