mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter.git
synced 2024-12-18 08:30:52 +00:00
cf4ac34420
With this patch, filters which are both enabled and throttled have an "actions automatically disabled" label together with "enabled" and the row is displayed in red. Plus, some minor changes like removing unused fields from sortable ones and added a comment to getQueryInfo about used columns (the idea is that it'll be easy to understand if a given column is already there, plus if we'll need the missing one we may just replace it with '*'). Bug: T154206 Change-Id: Iab157d094cbf2d50e9db537535fd48243e74af0b
300 lines
7.7 KiB
PHP
300 lines
7.7 KiB
PHP
<?php
|
|
|
|
use MediaWiki\Linker\LinkRenderer;
|
|
|
|
/**
|
|
* Class to build paginated filter list
|
|
*/
|
|
class AbuseFilterPager extends TablePager {
|
|
|
|
/**
|
|
* @var LinkRenderer
|
|
*/
|
|
protected $linkRenderer;
|
|
|
|
public $mPage, $mConds, $mQuery;
|
|
|
|
/**
|
|
* @param AbuseFilterViewList $page
|
|
* @param array $conds
|
|
* @param LinkRenderer $linkRenderer
|
|
* @param array $query
|
|
*/
|
|
public function __construct( $page, $conds, $linkRenderer, $query ) {
|
|
$this->mPage = $page;
|
|
$this->mConds = $conds;
|
|
$this->linkRenderer = $linkRenderer;
|
|
$this->mQuery = $query;
|
|
parent::__construct( $this->mPage->getContext() );
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getQueryInfo() {
|
|
return [
|
|
'tables' => [ 'abuse_filter' ],
|
|
'fields' => [
|
|
// All columns but af_comments
|
|
'af_id',
|
|
'af_enabled',
|
|
'af_deleted',
|
|
'af_pattern',
|
|
'af_global',
|
|
'af_public_comments',
|
|
'af_hidden',
|
|
'af_hit_count',
|
|
'af_timestamp',
|
|
'af_user_text',
|
|
'af_user',
|
|
'af_actions',
|
|
'af_group',
|
|
'af_throttled'
|
|
],
|
|
'conds' => $this->mConds,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @see Pager::getFieldNames()
|
|
* @return array
|
|
*/
|
|
public function getFieldNames() {
|
|
static $headers = null;
|
|
|
|
if ( !empty( $headers ) ) {
|
|
return $headers;
|
|
}
|
|
|
|
$headers = [
|
|
'af_id' => 'abusefilter-list-id',
|
|
'af_public_comments' => 'abusefilter-list-public',
|
|
'af_actions' => 'abusefilter-list-consequences',
|
|
'af_enabled' => 'abusefilter-list-status',
|
|
'af_timestamp' => 'abusefilter-list-lastmodified',
|
|
'af_hidden' => 'abusefilter-list-visibility',
|
|
];
|
|
|
|
if ( $this->mPage->getUser()->isAllowed( 'abusefilter-log-detail' ) ) {
|
|
$headers['af_hit_count'] = 'abusefilter-list-hitcount';
|
|
}
|
|
|
|
if ( AbuseFilterView::canViewPrivate() && !empty( $this->mQuery[0] ) ) {
|
|
$headers['af_pattern'] = 'abusefilter-list-pattern';
|
|
}
|
|
|
|
if ( count( $this->getConfig()->get( 'AbuseFilterValidGroups' ) ) > 1 ) {
|
|
$headers['af_group'] = 'abusefilter-list-group';
|
|
}
|
|
|
|
foreach ( $headers as &$msg ) {
|
|
$msg = $this->msg( $msg )->text();
|
|
}
|
|
|
|
return $headers;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param string $value
|
|
* @return string
|
|
*/
|
|
public function formatValue( $name, $value ) {
|
|
$lang = $this->getLanguage();
|
|
$row = $this->mCurrentRow;
|
|
|
|
switch ( $name ) {
|
|
case 'af_id':
|
|
return $this->linkRenderer->makeLink(
|
|
SpecialPage::getTitleFor( 'AbuseFilter', intval( $value ) ),
|
|
$lang->formatNum( intval( $value ) )
|
|
);
|
|
case 'af_pattern':
|
|
if ( $this->mQuery[1] === 'LIKE' ) {
|
|
$position = mb_strpos(
|
|
strtolower( $row->af_pattern ),
|
|
strtolower( $this->mQuery[0] ),
|
|
0,
|
|
'UTF8'
|
|
);
|
|
if ( $position === false ) {
|
|
// This may happen due to problems with character encoding
|
|
// which aren't easy to solve
|
|
return htmlspecialchars( mb_substr( $row->af_pattern, 0, 50, 'UTF8' ) );
|
|
}
|
|
$length = mb_strlen( $this->mQuery[0], 'UTF8' );
|
|
} elseif ( $this->mQuery[1] === 'RLIKE' ) {
|
|
Wikimedia\suppressWarnings();
|
|
$check = preg_match(
|
|
'/' . $this->mQuery[0] . '/',
|
|
$row->af_pattern,
|
|
$matches,
|
|
PREG_OFFSET_CAPTURE
|
|
);
|
|
Wikimedia\restoreWarnings();
|
|
// This may happen in case of catastrophic backtracking
|
|
if ( $check === false ) {
|
|
return htmlspecialchars( mb_substr( $row->af_pattern, 0, 50, 'UTF8' ) );
|
|
}
|
|
$length = mb_strlen( $matches[0][0], 'UTF8' );
|
|
$position = $matches[0][1];
|
|
} elseif ( $this->mQuery[1] === 'IRLIKE' ) {
|
|
Wikimedia\suppressWarnings();
|
|
$check = preg_match(
|
|
'/' . $this->mQuery[0] . '/i',
|
|
$row->af_pattern,
|
|
$matches,
|
|
PREG_OFFSET_CAPTURE
|
|
);
|
|
Wikimedia\restoreWarnings();
|
|
// This may happen in case of catastrophic backtracking
|
|
if ( $check === false ) {
|
|
return htmlspecialchars( mb_substr( $row->af_pattern, 0, 50, 'UTF8' ) );
|
|
}
|
|
$length = mb_strlen( $matches[0][0], 'UTF8' );
|
|
$position = $matches[0][1];
|
|
}
|
|
$remaining = 50 - $length;
|
|
if ( $remaining <= 0 ) {
|
|
$pattern = '<b>' .
|
|
htmlspecialchars( mb_substr( $row->af_pattern, 0, 50, 'UTF8' ) ) .
|
|
'</b>';
|
|
} else {
|
|
$minoffset = max( $position - round( $remaining / 2 ), 0 );
|
|
$pattern = mb_substr( $row->af_pattern, $minoffset, 50, 'UTF8' );
|
|
$pattern =
|
|
htmlspecialchars( mb_substr( $pattern, 0, $position - $minoffset, 'UTF8' ) ) .
|
|
'<b>' .
|
|
htmlspecialchars( mb_substr( $pattern, $position - $minoffset, $length, 'UTF8' ) ) .
|
|
'</b>' .
|
|
htmlspecialchars( mb_substr(
|
|
$pattern,
|
|
$position - $minoffset + $length,
|
|
$remaining - ( $position - $minoffset + $length ),
|
|
'UTF8'
|
|
)
|
|
);
|
|
}
|
|
return $pattern;
|
|
case 'af_public_comments':
|
|
return $this->linkRenderer->makeLink(
|
|
SpecialPage::getTitleFor( 'AbuseFilter', intval( $row->af_id ) ),
|
|
$value
|
|
);
|
|
case 'af_actions':
|
|
$actions = explode( ',', $value );
|
|
$displayActions = [];
|
|
foreach ( $actions as $action ) {
|
|
$displayActions[] = AbuseFilter::getActionDisplay( $action );
|
|
}
|
|
return htmlspecialchars( $lang->commaList( $displayActions ) );
|
|
case 'af_enabled':
|
|
$statuses = [];
|
|
if ( $row->af_deleted ) {
|
|
$statuses[] = $this->msg( 'abusefilter-deleted' )->parse();
|
|
} elseif ( $row->af_enabled ) {
|
|
$statuses[] = $this->msg( 'abusefilter-enabled' )->parse();
|
|
if ( $row->af_throttled ) {
|
|
$statuses[] = $this->msg( 'abusefilter-throttled' )->parse();
|
|
}
|
|
} else {
|
|
$statuses[] = $this->msg( 'abusefilter-disabled' )->parse();
|
|
}
|
|
|
|
if ( $row->af_global && $this->getConfig()->get( 'AbuseFilterIsCentral' ) ) {
|
|
$statuses[] = $this->msg( 'abusefilter-status-global' )->parse();
|
|
}
|
|
|
|
return $lang->commaList( $statuses );
|
|
case 'af_hidden':
|
|
$msg = $value ? 'abusefilter-hidden' : 'abusefilter-unhidden';
|
|
return $this->msg( $msg )->parse();
|
|
case 'af_hit_count':
|
|
if ( SpecialAbuseLog::canSeeDetails( $row->af_id, $row->af_hidden ) ) {
|
|
$count_display = $this->msg( 'abusefilter-hitcount' )
|
|
->numParams( $value )->parse();
|
|
$link = $this->linkRenderer->makeKnownLink(
|
|
SpecialPage::getTitleFor( 'AbuseLog' ),
|
|
$count_display,
|
|
[],
|
|
[ 'wpSearchFilter' => $row->af_id ]
|
|
);
|
|
} else {
|
|
$link = "";
|
|
}
|
|
return $link;
|
|
case 'af_timestamp':
|
|
$userLink =
|
|
Linker::userLink(
|
|
$row->af_user,
|
|
$row->af_user_text
|
|
) .
|
|
Linker::userToolLinks(
|
|
$row->af_user,
|
|
$row->af_user_text
|
|
);
|
|
$user = $row->af_user_text;
|
|
return $this->msg( 'abusefilter-edit-lastmod-text' )
|
|
->rawParams(
|
|
$lang->timeanddate( $value, true ),
|
|
$userLink,
|
|
$lang->date( $value, true ),
|
|
$lang->time( $value, true ),
|
|
$user
|
|
)->parse();
|
|
case 'af_group':
|
|
return AbuseFilter::nameGroup( $value );
|
|
break;
|
|
default:
|
|
throw new MWException( "Unknown row type $name!" );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getDefaultSort() {
|
|
return 'af_id';
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getTableClass() {
|
|
return 'TablePager mw-abusefilter-list-scrollable';
|
|
}
|
|
|
|
/**
|
|
* @see TablePager::getRowClass()
|
|
* @param stdClass $row
|
|
* @return string
|
|
*/
|
|
public function getRowClass( $row ) {
|
|
if ( $row->af_enabled ) {
|
|
return $row->af_throttled ? 'mw-abusefilter-list-throttled' : 'mw-abusefilter-list-enabled';
|
|
} elseif ( $row->af_deleted ) {
|
|
return 'mw-abusefilter-list-deleted';
|
|
} else {
|
|
return 'mw-abusefilter-list-disabled';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @return bool
|
|
*/
|
|
public function isFieldSortable( $name ) {
|
|
$sortable_fields = [
|
|
'af_id',
|
|
'af_enabled',
|
|
'af_timestamp',
|
|
'af_hidden',
|
|
'af_group',
|
|
];
|
|
if ( $this->mPage->getUser()->isAllowed( 'abusefilter-log-detail' ) ) {
|
|
$sortable_fields[] = 'af_hit_count';
|
|
}
|
|
return in_array( $name, $sortable_fields );
|
|
}
|
|
}
|