diff options
Diffstat (limited to 'AbuseFilter/includes/Views/AbuseFilterViewList.php')
-rw-r--r-- | AbuseFilter/includes/Views/AbuseFilterViewList.php | 199 |
1 files changed, 96 insertions, 103 deletions
diff --git a/AbuseFilter/includes/Views/AbuseFilterViewList.php b/AbuseFilter/includes/Views/AbuseFilterViewList.php index ad92ad6c..efbf6217 100644 --- a/AbuseFilter/includes/Views/AbuseFilterViewList.php +++ b/AbuseFilter/includes/Views/AbuseFilterViewList.php @@ -1,5 +1,7 @@ <?php +use MediaWiki\MediaWikiServices; + /** * The default view used in Special:AbuseFilter */ @@ -11,6 +13,7 @@ class AbuseFilterViewList extends AbuseFilterView { $out = $this->getOutput(); $request = $this->getRequest(); $config = $this->getConfig(); + $user = $this->getUser(); // Show filter performance statistics $this->showStatus(); @@ -18,18 +21,27 @@ class AbuseFilterViewList extends AbuseFilterView { $out->addWikiMsg( 'abusefilter-intro' ); // New filter button - if ( $this->canEdit() ) { + if ( AbuseFilter::canEdit( $user ) ) { $out->enableOOUI(); - $link = new OOUI\ButtonWidget( [ - 'label' => $this->msg( 'abusefilter-new' )->text(), - 'href' => $this->getTitle( 'new' )->getFullURL(), + $buttons = new OOUI\HorizontalLayout( [ + 'items' => [ + new OOUI\ButtonWidget( [ + 'label' => $this->msg( 'abusefilter-new' )->text(), + 'href' => $this->getTitle( 'new' )->getFullURL(), + ] ), + new OOUI\ButtonWidget( [ + 'label' => $this->msg( 'abusefilter-import-button' )->text(), + 'href' => $this->getTitle( 'import' )->getFullURL(), + ] ) + ] ] ); - $out->addHTML( $link ); + $out->addHTML( $buttons ); } $conds = []; $deleted = $request->getVal( 'deletedfilters' ); $furtherOptions = $request->getArray( 'furtheroptions', [] ); + '@phan-var array $furtherOptions'; // Backward compatibility with old links if ( $request->getBool( 'hidedisabled' ) ) { $furtherOptions[] = 'hidedisabled'; @@ -45,22 +57,22 @@ class AbuseFilterViewList extends AbuseFilterView { } $scope = $request->getVal( 'rulescope', $defaultscope ); - $searchEnabled = $this->canViewPrivate() && !( + $searchEnabled = AbuseFilter::canViewPrivate( $user ) && !( $config->get( 'AbuseFilterCentralDB' ) !== null && !$config->get( 'AbuseFilterIsCentral' ) && - $scope == 'global' ); + $scope === 'global' ); if ( $searchEnabled ) { - $querypattern = $request->getVal( 'querypattern' ); + $querypattern = $request->getVal( 'querypattern', '' ); $searchmode = $request->getVal( 'searchoption', 'LIKE' ); } else { $querypattern = ''; $searchmode = ''; } - if ( $deleted == 'show' ) { + if ( $deleted === 'show' ) { // Nothing - } elseif ( $deleted == 'only' ) { + } elseif ( $deleted === 'only' ) { $conds['af_deleted'] = 1; } else { // hide, or anything else. @@ -75,79 +87,57 @@ class AbuseFilterViewList extends AbuseFilterView { $conds['af_hidden'] = 0; } - if ( $scope == 'local' ) { + if ( $scope === 'local' ) { $conds['af_global'] = 0; - } elseif ( $scope == 'global' ) { + } elseif ( $scope === 'global' ) { $conds['af_global'] = 1; } - $dbr = wfGetDB( DB_REPLICA ); - if ( $querypattern !== '' ) { - if ( $searchmode !== 'LIKE' ) { - // Check regex pattern validity - Wikimedia\suppressWarnings(); - $validreg = preg_match( '/' . $querypattern . '/', null ); - Wikimedia\restoreWarnings(); + // Check the search pattern. Filtering the results is done in AbuseFilterPager + $error = null; + if ( !in_array( $searchmode, [ 'LIKE', 'RLIKE', 'IRLIKE' ] ) ) { + $error = 'abusefilter-list-invalid-searchmode'; + } elseif ( $searchmode !== 'LIKE' && !StringUtils::isValidPCRERegex( "/$querypattern/" ) ) { + $error = 'abusefilter-list-regexerror'; + } - if ( $validreg === false ) { - $out->addHTML( - Xml::tags( - 'p', - null, - Html::errorBox( $this->msg( 'abusefilter-list-regexerror' )->parse() ) - ) - ); - $this->showList( - [ 'af_deleted' => 0 ], - compact( - 'deleted', - 'furtherOptions', - 'querypattern', - 'searchmode', - 'scope', - 'searchEnabled' - ) - ); - return; - } - if ( $searchmode === 'RLIKE' ) { - $conds[] = 'af_pattern RLIKE ' . - $dbr->addQuotes( $querypattern ); - } else { - $conds[] = 'LOWER( CAST( af_pattern AS char ) ) RLIKE ' . - strtolower( $dbr->addQuotes( $querypattern ) ); - } - } else { - // Build like query escaping tokens and encapsulating in % to search everywhere - $conds[] = 'LOWER( CAST( af_pattern AS char ) ) ' . - $dbr->buildLike( - $dbr->anyString(), - strtolower( $querypattern ), - $dbr->anyString() - ); + if ( $error !== null ) { + $out->addHTML( + Xml::tags( + 'p', + null, + Html::errorBox( $this->msg( $error )->escaped() ) + ) + ); + + // Reset the conditions in case of error + $conds = [ 'af_deleted' => 0 ]; + $querypattern = ''; } } $this->showList( - $conds, compact( 'deleted', 'furtherOptions', 'querypattern', 'searchmode', - 'scope', - 'searchEnabled' - ) + 'scope' + ), + $conds ); } /** - * @param array $conds * @param array $optarray + * @param array $conds */ - public function showList( $conds = [ 'af_deleted' => 0 ], $optarray = [] ) { + private function showList( array $optarray, array $conds = [ 'af_deleted' => 0 ] ) { + $user = $this->getUser(); $config = $this->getConfig(); + $centralDB = $config->get( 'AbuseFilterCentralDB' ); + $dbIsCentral = $config->get( 'AbuseFilterIsCentral' ); $this->getOutput()->addHTML( Xml::tags( 'h2', null, $this->msg( 'abusefilter-list' )->parse() ) ); @@ -155,15 +145,10 @@ class AbuseFilterViewList extends AbuseFilterView { $deleted = $optarray['deleted']; $furtherOptions = $optarray['furtherOptions']; $scope = $optarray['scope']; - $searchEnabled = $optarray['searchEnabled']; $querypattern = $optarray['querypattern']; $searchmode = $optarray['searchmode']; - if ( - $config->get( 'AbuseFilterCentralDB' ) !== null - && !$config->get( 'AbuseFilterIsCentral' ) - && $scope == 'global' - ) { + if ( $centralDB !== null && !$dbIsCentral && $scope === 'global' ) { $pager = new GlobalAbuseFilterPager( $this, $conds, @@ -174,31 +159,20 @@ class AbuseFilterViewList extends AbuseFilterView { $this, $conds, $this->linkRenderer, - [ $querypattern, $searchmode ] + $querypattern, + $searchmode ); } // Options form $formDescriptor = []; - $formDescriptor['deletedfilters'] = [ - 'name' => 'deletedfilters', - 'type' => 'radio', - 'flatlist' => true, - 'label-message' => 'abusefilter-list-options-deleted', - 'options-messages' => [ - 'abusefilter-list-options-deleted-show' => 'show', - 'abusefilter-list-options-deleted-hide' => 'hide', - 'abusefilter-list-options-deleted-only' => 'only', - ], - 'default' => $deleted, - ]; - if ( $config->get( 'AbuseFilterCentralDB' ) !== null ) { + if ( $centralDB !== null ) { $optionsMsg = [ 'abusefilter-list-options-scope-local' => 'local', 'abusefilter-list-options-scope-global' => 'global', ]; - if ( $config->get( 'AbuseFilterIsCentral' ) ) { + if ( $dbIsCentral ) { // For central wiki: add third scope option $optionsMsg['abusefilter-list-options-scope-all'] = 'all'; } @@ -212,6 +186,19 @@ class AbuseFilterViewList extends AbuseFilterView { ]; } + $formDescriptor['deletedfilters'] = [ + 'name' => 'deletedfilters', + 'type' => 'radio', + 'flatlist' => true, + 'label-message' => 'abusefilter-list-options-deleted', + 'options-messages' => [ + 'abusefilter-list-options-deleted-show' => 'show', + 'abusefilter-list-options-deleted-hide' => 'hide', + 'abusefilter-list-options-deleted-only' => 'only', + ], + 'default' => $deleted, + ]; + $formDescriptor['furtheroptions'] = [ 'name' => 'furtheroptions', 'type' => 'multiselect', @@ -224,11 +211,12 @@ class AbuseFilterViewList extends AbuseFilterView { 'default' => $furtherOptions ]; - // ToDo: Since this is only for saving space, we should convert it to use a 'hide-if' - if ( $searchEnabled ) { + if ( AbuseFilter::canViewPrivate( $user ) ) { + $globalEnabled = $centralDB !== null && !$dbIsCentral; $formDescriptor['querypattern'] = [ 'name' => 'querypattern', 'type' => 'text', + 'hide-if' => $globalEnabled ? [ '===', 'rulescope', 'global' ] : [], 'label-message' => 'abusefilter-list-options-searchfield', 'placeholder' => $this->msg( 'abusefilter-list-options-searchpattern' )->text(), 'default' => $querypattern @@ -239,6 +227,9 @@ class AbuseFilterViewList extends AbuseFilterView { 'type' => 'radio', 'flatlist' => true, 'label-message' => 'abusefilter-list-options-searchoptions', + 'hide-if' => $globalEnabled ? + [ 'OR', [ '===', 'querypattern', '' ], $formDescriptor['querypattern']['hide-if'] ] : + [ '===', 'querypattern', '' ], 'options-messages' => [ 'abusefilter-list-options-search-like' => 'LIKE', 'abusefilter-list-options-search-rlike' => 'RLIKE', @@ -265,37 +256,39 @@ class AbuseFilterViewList extends AbuseFilterView { ->prepareForm() ->displayForm( false ); - $this->getOutput()->addHTML( - $pager->getNavigationBar() . - $pager->getBody() . - $pager->getNavigationBar() - ); + $this->getOutput()->addParserOutputContent( $pager->getFullOutput() ); } /** - * Show stats + * Generates a summary of filter activity using the internal statistics. */ public function showStatus() { - $stash = ObjectCache::getMainStashInstance(); - $overflow_count = (int)$stash->get( AbuseFilter::filterLimitReachedKey() ); - $match_count = (int)$stash->get( AbuseFilter::filterMatchesKey() ); - $total_count = 0; + $stash = MediaWikiServices::getInstance()->getMainObjectStash(); + + $totalCount = 0; + $matchCount = 0; + $overflowCount = 0; foreach ( $this->getConfig()->get( 'AbuseFilterValidGroups' ) as $group ) { - $total_count += (int)$stash->get( AbuseFilter::filterUsedKey( $group ) ); + $profile = $stash->get( AbuseFilter::filterProfileGroupKey( $group ) ); + if ( $profile !== false ) { + $totalCount += $profile[ 'total' ]; + $overflowCount += $profile[ 'overflow' ]; + $matchCount += $profile[ 'matches' ]; + } } - if ( $total_count > 0 ) { - $overflow_percent = sprintf( "%.2f", 100 * $overflow_count / $total_count ); - $match_percent = sprintf( "%.2f", 100 * $match_count / $total_count ); + if ( $totalCount > 0 ) { + $overflowPercent = round( 100 * $overflowCount / $totalCount, 2 ); + $matchPercent = round( 100 * $matchCount / $totalCount, 2 ); $status = $this->msg( 'abusefilter-status' ) ->numParams( - $total_count, - $overflow_count, - $overflow_percent, + $totalCount, + $overflowCount, + $overflowPercent, $this->getConfig()->get( 'AbuseFilterConditionLimit' ), - $match_count, - $match_percent + $matchCount, + $matchPercent )->parse(); $status = Xml::tags( 'div', [ 'class' => 'mw-abusefilter-status' ], $status ); |