2009-01-23 19:23:19 +00:00
|
|
|
<?php
|
|
|
|
|
2020-11-29 10:53:29 +00:00
|
|
|
namespace MediaWiki\Extension\AbuseFilter\View;
|
|
|
|
|
|
|
|
use HtmlArmor;
|
2023-11-16 18:52:51 +00:00
|
|
|
use LogicException;
|
2024-06-12 18:01:35 +00:00
|
|
|
use MediaWiki\Context\IContextSource;
|
2020-10-23 14:19:02 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager;
|
2020-12-18 14:05:33 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesRegistry;
|
2021-02-01 15:47:46 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\EditBox\EditBoxBuilderFactory;
|
2020-09-20 14:50:37 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\Filter\Filter;
|
2020-09-20 11:30:59 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\Filter\FilterNotFoundException;
|
|
|
|
use MediaWiki\Extension\AbuseFilter\Filter\FilterVersionNotFoundException;
|
2020-09-20 14:50:37 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\Filter\MutableFilter;
|
2020-10-23 14:19:02 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\FilterImporter;
|
2020-09-20 11:30:59 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\FilterLookup;
|
2020-10-23 14:19:02 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\FilterProfiler;
|
|
|
|
use MediaWiki\Extension\AbuseFilter\FilterStore;
|
2020-10-15 22:00:32 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\InvalidImportDataException;
|
2020-10-02 15:08:48 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\SpecsFormatter;
|
2023-12-10 19:03:19 +00:00
|
|
|
use MediaWiki\Html\Html;
|
|
|
|
use MediaWiki\Linker\Linker;
|
2020-10-03 17:13:32 +00:00
|
|
|
use MediaWiki\Linker\LinkRenderer;
|
2023-06-12 08:27:03 +00:00
|
|
|
use MediaWiki\MainConfigNames;
|
2020-10-23 14:19:02 +00:00
|
|
|
use MediaWiki\Permissions\PermissionManager;
|
2023-12-10 19:03:19 +00:00
|
|
|
use MediaWiki\SpecialPage\SpecialPage;
|
2024-06-12 18:01:35 +00:00
|
|
|
use MediaWiki\Xml\Xml;
|
2020-11-29 10:53:29 +00:00
|
|
|
use OOUI;
|
2024-11-13 12:02:15 +00:00
|
|
|
use StatusValue;
|
2023-06-07 15:41:20 +00:00
|
|
|
use UnexpectedValueException;
|
2024-10-19 19:55:40 +00:00
|
|
|
use Wikimedia\Rdbms\IDBAccessObject;
|
2024-04-30 18:21:20 +00:00
|
|
|
use Wikimedia\Rdbms\IExpression;
|
2023-02-26 12:51:08 +00:00
|
|
|
use Wikimedia\Rdbms\LBFactory;
|
2024-04-30 18:21:20 +00:00
|
|
|
use Wikimedia\Rdbms\LikeValue;
|
|
|
|
use Wikimedia\Rdbms\SelectQueryBuilder;
|
2019-09-18 21:48:40 +00:00
|
|
|
|
2009-01-23 19:23:19 +00:00
|
|
|
class AbuseFilterViewEdit extends AbuseFilterView {
|
2020-10-03 13:05:20 +00:00
|
|
|
/**
|
|
|
|
* @var int|null The history ID of the current filter
|
|
|
|
*/
|
|
|
|
private $historyID;
|
2020-10-03 17:13:32 +00:00
|
|
|
/** @var int|string */
|
|
|
|
private $filter;
|
2020-10-03 13:05:20 +00:00
|
|
|
|
2023-02-26 12:51:08 +00:00
|
|
|
/** @var LBFactory */
|
|
|
|
private $lbFactory;
|
|
|
|
|
2020-10-23 14:19:02 +00:00
|
|
|
/** @var PermissionManager */
|
|
|
|
private $permissionManager;
|
|
|
|
|
|
|
|
/** @var FilterProfiler */
|
|
|
|
private $filterProfiler;
|
|
|
|
|
|
|
|
/** @var FilterLookup */
|
|
|
|
private $filterLookup;
|
|
|
|
|
|
|
|
/** @var FilterImporter */
|
|
|
|
private $filterImporter;
|
|
|
|
|
|
|
|
/** @var FilterStore */
|
|
|
|
private $filterStore;
|
|
|
|
|
|
|
|
/** @var EditBoxBuilderFactory */
|
|
|
|
private $boxBuilderFactory;
|
|
|
|
|
2020-11-29 22:55:34 +00:00
|
|
|
/** @var ConsequencesRegistry */
|
|
|
|
private $consequencesRegistry;
|
|
|
|
|
2020-10-02 15:08:48 +00:00
|
|
|
/** @var SpecsFormatter */
|
|
|
|
private $specsFormatter;
|
|
|
|
|
2012-09-02 11:07:02 +00:00
|
|
|
/**
|
2023-02-26 12:51:08 +00:00
|
|
|
* @param LBFactory $lbFactory
|
2020-10-23 14:19:02 +00:00
|
|
|
* @param PermissionManager $permissionManager
|
|
|
|
* @param AbuseFilterPermissionManager $afPermManager
|
|
|
|
* @param FilterProfiler $filterProfiler
|
|
|
|
* @param FilterLookup $filterLookup
|
|
|
|
* @param FilterImporter $filterImporter
|
|
|
|
* @param FilterStore $filterStore
|
|
|
|
* @param EditBoxBuilderFactory $boxBuilderFactory
|
2020-11-29 22:55:34 +00:00
|
|
|
* @param ConsequencesRegistry $consequencesRegistry
|
2020-10-02 15:08:48 +00:00
|
|
|
* @param SpecsFormatter $specsFormatter
|
2020-10-03 17:13:32 +00:00
|
|
|
* @param IContextSource $context
|
|
|
|
* @param LinkRenderer $linkRenderer
|
2020-10-16 22:36:15 +00:00
|
|
|
* @param string $basePageName
|
2012-09-02 11:07:02 +00:00
|
|
|
* @param array $params
|
|
|
|
*/
|
2020-10-16 22:36:15 +00:00
|
|
|
public function __construct(
|
2023-02-26 12:51:08 +00:00
|
|
|
LBFactory $lbFactory,
|
2020-10-23 14:19:02 +00:00
|
|
|
PermissionManager $permissionManager,
|
|
|
|
AbuseFilterPermissionManager $afPermManager,
|
|
|
|
FilterProfiler $filterProfiler,
|
|
|
|
FilterLookup $filterLookup,
|
|
|
|
FilterImporter $filterImporter,
|
|
|
|
FilterStore $filterStore,
|
|
|
|
EditBoxBuilderFactory $boxBuilderFactory,
|
2020-11-29 22:55:34 +00:00
|
|
|
ConsequencesRegistry $consequencesRegistry,
|
2020-10-02 15:08:48 +00:00
|
|
|
SpecsFormatter $specsFormatter,
|
2020-10-16 22:36:15 +00:00
|
|
|
IContextSource $context,
|
|
|
|
LinkRenderer $linkRenderer,
|
|
|
|
string $basePageName,
|
|
|
|
array $params
|
|
|
|
) {
|
2020-10-23 14:19:02 +00:00
|
|
|
parent::__construct( $afPermManager, $context, $linkRenderer, $basePageName, $params );
|
2023-02-26 12:51:08 +00:00
|
|
|
$this->lbFactory = $lbFactory;
|
2020-10-23 14:19:02 +00:00
|
|
|
$this->permissionManager = $permissionManager;
|
|
|
|
$this->filterProfiler = $filterProfiler;
|
|
|
|
$this->filterLookup = $filterLookup;
|
|
|
|
$this->filterImporter = $filterImporter;
|
|
|
|
$this->filterStore = $filterStore;
|
|
|
|
$this->boxBuilderFactory = $boxBuilderFactory;
|
2020-11-29 22:55:34 +00:00
|
|
|
$this->consequencesRegistry = $consequencesRegistry;
|
2020-10-02 15:08:48 +00:00
|
|
|
$this->specsFormatter = $specsFormatter;
|
|
|
|
$this->specsFormatter->setMessageLocalizer( $this->getContext() );
|
2020-10-03 17:13:32 +00:00
|
|
|
$this->filter = $this->mParams['filter'];
|
2020-10-03 13:05:20 +00:00
|
|
|
$this->historyID = $this->mParams['history'] ?? null;
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
|
2018-04-04 21:14:25 +00:00
|
|
|
/**
|
|
|
|
* Shows the page
|
|
|
|
*/
|
|
|
|
public function show() {
|
2011-11-16 05:34:24 +00:00
|
|
|
$out = $this->getOutput();
|
2020-09-23 21:42:54 +00:00
|
|
|
$out->enableOOUI();
|
2011-11-16 05:34:24 +00:00
|
|
|
$request = $this->getRequest();
|
2023-09-22 20:43:01 +00:00
|
|
|
$out->setPageTitleMsg( $this->msg( 'abusefilter-edit' ) );
|
2015-03-29 12:38:53 +00:00
|
|
|
$out->addHelpLink( 'Extension:AbuseFilter/Rules format' );
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-12-02 18:08:37 +00:00
|
|
|
if ( !is_numeric( $this->filter ) && $this->filter !== null ) {
|
2020-09-23 21:42:54 +00:00
|
|
|
$this->showUnrecoverableError( 'abusefilter-edit-badfilter' );
|
2019-08-28 14:06:33 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-12-02 18:08:37 +00:00
|
|
|
$filter = $this->filter ? (int)$this->filter : null;
|
2020-10-03 13:05:20 +00:00
|
|
|
$history_id = $this->historyID;
|
|
|
|
if ( $this->historyID ) {
|
2023-02-26 12:51:08 +00:00
|
|
|
$dbr = $this->lbFactory->getReplicaDatabase();
|
2024-04-30 18:21:20 +00:00
|
|
|
$lastID = (int)$dbr->newSelectQueryBuilder()
|
|
|
|
->select( 'afh_id' )
|
|
|
|
->from( 'abuse_filter_history' )
|
|
|
|
->where( [
|
2016-12-02 18:05:36 +00:00
|
|
|
'afh_filter' => $filter,
|
2024-04-30 18:21:20 +00:00
|
|
|
] )
|
|
|
|
->orderBy( 'afh_id', SelectQueryBuilder::SORT_DESC )
|
|
|
|
->caller( __METHOD__ )
|
|
|
|
->fetchField();
|
2016-12-02 18:05:36 +00:00
|
|
|
// change $history_id to null if it's current version id
|
2020-10-03 13:05:20 +00:00
|
|
|
if ( $lastID === $this->historyID ) {
|
2016-12-02 18:05:36 +00:00
|
|
|
$history_id = null;
|
|
|
|
}
|
|
|
|
}
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2014-10-04 14:42:46 +00:00
|
|
|
// Add the default warning and disallow messages in a JS variable
|
|
|
|
$this->exposeMessages();
|
2012-06-06 05:18:31 +00:00
|
|
|
|
2022-07-02 13:35:00 +00:00
|
|
|
$canEdit = $this->afPermManager->canEdit( $this->getAuthority() );
|
2020-02-08 13:55:12 +00:00
|
|
|
|
2020-09-20 10:18:46 +00:00
|
|
|
if ( $filter === null && !$canEdit ) {
|
2020-09-23 21:42:54 +00:00
|
|
|
// Special case: Special:AbuseFilter/new is certainly not usable if the user cannot edit
|
|
|
|
$this->showUnrecoverableError( 'abusefilter-edit-notallowed' );
|
2009-09-18 10:05:20 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2020-09-22 22:19:50 +00:00
|
|
|
$isImport = $request->wasPosted() && $request->getRawVal( 'wpImportText' ) !== null;
|
2019-03-01 14:24:30 +00:00
|
|
|
|
2020-09-23 21:42:54 +00:00
|
|
|
if ( !$isImport && $request->wasPosted() && $canEdit ) {
|
|
|
|
$this->attemptSave( $filter, $history_id );
|
2019-03-01 14:24:30 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-22 22:19:50 +00:00
|
|
|
if ( $isImport ) {
|
2020-09-20 11:30:59 +00:00
|
|
|
$filterObj = $this->loadImportRequest();
|
|
|
|
if ( $filterObj === null ) {
|
2020-09-23 21:42:54 +00:00
|
|
|
$this->showUnrecoverableError( 'abusefilter-import-invalid-data' );
|
2020-09-22 22:19:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-02-08 13:55:12 +00:00
|
|
|
} else {
|
2020-09-23 21:42:54 +00:00
|
|
|
// The request wasn't posted (i.e. just viewing the filter) or the user cannot edit
|
2020-09-20 14:50:37 +00:00
|
|
|
try {
|
2020-09-20 11:30:59 +00:00
|
|
|
$filterObj = $this->loadFromDatabase( $filter, $history_id );
|
|
|
|
} catch ( FilterNotFoundException $_ ) {
|
|
|
|
$filterObj = null;
|
2020-09-20 14:50:37 +00:00
|
|
|
}
|
2020-09-20 11:30:59 +00:00
|
|
|
if ( $filterObj === null || ( $history_id && (int)$filterObj->getID() !== $filter ) ) {
|
2020-09-23 21:42:54 +00:00
|
|
|
$this->showUnrecoverableError( 'abusefilter-edit-badfilter' );
|
|
|
|
return;
|
|
|
|
}
|
2020-02-08 13:55:12 +00:00
|
|
|
}
|
|
|
|
|
2020-09-20 11:30:59 +00:00
|
|
|
$this->buildFilterEditor( null, $filterObj, $filter, $history_id );
|
2020-02-08 13:55:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-09-20 10:18:46 +00:00
|
|
|
* @param int|null $filter The filter ID or null for a new filter
|
2020-02-08 13:55:12 +00:00
|
|
|
* @param int|null $history_id The history ID of the filter, if applicable. Otherwise null
|
|
|
|
*/
|
2021-07-21 18:51:12 +00:00
|
|
|
private function attemptSave( ?int $filter, $history_id ): void {
|
2020-02-08 13:55:12 +00:00
|
|
|
$out = $this->getOutput();
|
2020-09-23 21:42:54 +00:00
|
|
|
$request = $this->getRequest();
|
|
|
|
$user = $this->getUser();
|
|
|
|
|
2020-09-20 11:30:59 +00:00
|
|
|
[ $newFilter, $origFilter ] = $this->loadRequest( $filter );
|
2020-09-23 21:42:54 +00:00
|
|
|
|
2020-11-17 22:19:18 +00:00
|
|
|
$tokenFilter = $filter === null ? 'new' : (string)$filter;
|
2020-09-23 21:42:54 +00:00
|
|
|
$editToken = $request->getVal( 'wpEditToken' );
|
2024-05-04 08:14:01 +00:00
|
|
|
$tokenMatches = $this->getCsrfTokenSet()->matchToken( $editToken, [ 'abusefilter', $tokenFilter ] );
|
2020-09-23 21:42:54 +00:00
|
|
|
|
|
|
|
if ( !$tokenMatches ) {
|
|
|
|
// Token invalid or expired while the page was open, warn to retry
|
2024-11-13 12:02:15 +00:00
|
|
|
$status = StatusValue::newGood();
|
|
|
|
$status->warning( 'abusefilter-edit-token-not-match' );
|
|
|
|
$this->buildFilterEditor( $status, $newFilter, $filter, $history_id );
|
2020-09-23 21:42:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-23 14:19:02 +00:00
|
|
|
$status = $this->filterStore->saveFilter( $user, $filter, $newFilter, $origFilter );
|
2019-03-01 14:24:30 +00:00
|
|
|
|
|
|
|
if ( !$status->isGood() ) {
|
|
|
|
if ( $status->isOK() ) {
|
|
|
|
// Fixable error, show the editing interface
|
2024-11-13 12:02:15 +00:00
|
|
|
$this->buildFilterEditor( $status, $newFilter, $filter, $history_id );
|
2019-03-01 14:24:30 +00:00
|
|
|
} else {
|
2024-11-13 12:02:15 +00:00
|
|
|
$this->showUnrecoverableError( $status->getMessages()[0] );
|
2019-03-01 14:24:30 +00:00
|
|
|
}
|
|
|
|
} elseif ( $status->getValue() === false ) {
|
|
|
|
// No change
|
|
|
|
$out->redirect( $this->getTitle()->getLocalURL() );
|
|
|
|
} else {
|
|
|
|
// Everything went fine!
|
2024-03-16 18:52:48 +00:00
|
|
|
[ $new_id, $history_id ] = $status->getValue();
|
2019-03-01 14:24:30 +00:00
|
|
|
$out->redirect(
|
|
|
|
$this->getTitle()->getLocalURL(
|
|
|
|
[
|
|
|
|
'result' => 'success',
|
|
|
|
'changedfilter' => $new_id,
|
|
|
|
'changeid' => $history_id,
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-23 21:42:54 +00:00
|
|
|
/**
|
2024-07-28 12:25:34 +00:00
|
|
|
* @param string|\Wikimedia\Message\MessageSpecifier $msg
|
2020-09-23 21:42:54 +00:00
|
|
|
*/
|
2024-04-12 20:48:59 +00:00
|
|
|
private function showUnrecoverableError( $msg ): void {
|
2020-09-23 21:42:54 +00:00
|
|
|
$out = $this->getOutput();
|
|
|
|
|
2024-04-12 20:48:59 +00:00
|
|
|
$out->addHTML( Html::errorBox( $this->msg( $msg )->parseAsBlock() ) );
|
2020-09-23 21:42:54 +00:00
|
|
|
$href = $this->getTitle()->getFullURL();
|
|
|
|
$btn = new OOUI\ButtonWidget( [
|
|
|
|
'label' => $this->msg( 'abusefilter-return' )->text(),
|
|
|
|
'href' => $href
|
|
|
|
] );
|
|
|
|
$out->addHTML( $btn );
|
|
|
|
}
|
|
|
|
|
Simplify ViewEdit, last round
This deals with data inconsistencies in buildFilterEditor. Every
property of $row was tested in all 5 scenarios (also using Selenium) to
check when it's set. The result is in the normalizeRow method, which
aims to remove any inconsistencies, so that buildFilterEditor always
receives a "complete" row with all defaults set.
The code in buildFilterEditor is now cleaner (because there are no
isset() checks), and it gives us a unique place where we can set
defaults (rather than partly doing that in
loadRequest/loadFilterData/loadImport, and partly relying on isset).
This will be especially useful when introducing value objects to
represent filters, because now you just have to look at normalizeRow()
to tell which properties are allowed to be missing, and thus what "kind"
of filter object you need (see
I5f33227887c035e301313bbe24d1c1fefb75bc6a).
Additionally, reduce the properties that get passed around during
export/import, and make the selenium test try a roundtrip, rather than
relying on hardcoded data that may get outdated. A future patch will
refactor the import/export code.
Change-Id: Id52c466baaf6da18e2981f27a81ffdad3a509e78
2020-09-27 15:15:46 +00:00
|
|
|
/**
|
|
|
|
* Builds the full form for edit filters, adding it to the OutputPage. This method can be called in 5 different
|
2020-09-20 14:50:37 +00:00
|
|
|
* situations, for a total of 5 different data sources for $filterObj and $actions:
|
Simplify ViewEdit, last round
This deals with data inconsistencies in buildFilterEditor. Every
property of $row was tested in all 5 scenarios (also using Selenium) to
check when it's set. The result is in the normalizeRow method, which
aims to remove any inconsistencies, so that buildFilterEditor always
receives a "complete" row with all defaults set.
The code in buildFilterEditor is now cleaner (because there are no
isset() checks), and it gives us a unique place where we can set
defaults (rather than partly doing that in
loadRequest/loadFilterData/loadImport, and partly relying on isset).
This will be especially useful when introducing value objects to
represent filters, because now you just have to look at normalizeRow()
to tell which properties are allowed to be missing, and thus what "kind"
of filter object you need (see
I5f33227887c035e301313bbe24d1c1fefb75bc6a).
Additionally, reduce the properties that get passed around during
export/import, and make the selenium test try a roundtrip, rather than
relying on hardcoded data that may get outdated. A future patch will
refactor the import/export code.
Change-Id: Id52c466baaf6da18e2981f27a81ffdad3a509e78
2020-09-27 15:15:46 +00:00
|
|
|
* 1 - View the result of importing a filter
|
|
|
|
* 2 - Create a new filter
|
|
|
|
* 3 - Load the current version of an existing filter
|
|
|
|
* 4 - Load an old version of an existing filter
|
|
|
|
* 5 - Show the user input again if saving fails after one of the steps above
|
2019-03-01 14:24:30 +00:00
|
|
|
*
|
2024-11-13 12:02:15 +00:00
|
|
|
* @param StatusValue|null $status A status for showing warnings or errors above the filter box
|
2020-09-20 14:50:37 +00:00
|
|
|
* @param Filter $filterObj
|
2020-09-20 10:18:46 +00:00
|
|
|
* @param int|null $filter The filter ID, or null for a new filter
|
2018-05-25 23:31:49 +00:00
|
|
|
* @param int|null $history_id The history ID of the filter, if applicable. Otherwise null
|
2012-03-11 20:51:54 +00:00
|
|
|
*/
|
2023-06-23 10:28:06 +00:00
|
|
|
private function buildFilterEditor(
|
2024-11-13 12:02:15 +00:00
|
|
|
?StatusValue $status,
|
2020-09-20 14:50:37 +00:00
|
|
|
Filter $filterObj,
|
2020-09-20 10:18:46 +00:00
|
|
|
?int $filter,
|
2020-02-08 13:55:12 +00:00
|
|
|
$history_id
|
2019-03-01 14:24:30 +00:00
|
|
|
) {
|
2011-11-16 05:34:24 +00:00
|
|
|
$out = $this->getOutput();
|
2018-03-23 09:13:41 +00:00
|
|
|
$out->addJsConfigVars( 'isFilterEditor', true );
|
2011-11-22 16:08:18 +00:00
|
|
|
$lang = $this->getLanguage();
|
2011-11-16 05:34:24 +00:00
|
|
|
$user = $this->getUser();
|
2020-09-20 11:30:59 +00:00
|
|
|
$actions = $filterObj->getActions();
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2023-12-10 13:14:27 +00:00
|
|
|
$isCreatingNewFilter = $filter === null;
|
2012-12-15 10:18:25 +00:00
|
|
|
$out->addSubtitle( $this->msg(
|
2023-12-10 13:14:27 +00:00
|
|
|
$isCreatingNewFilter ? 'abusefilter-edit-subtitle-new' : 'abusefilter-edit-subtitle',
|
|
|
|
$isCreatingNewFilter ? $filter : $this->getLanguage()->formatNum( $filter ),
|
2020-09-09 05:38:20 +00:00
|
|
|
$history_id
|
2017-02-05 21:56:39 +00:00
|
|
|
)->parse() );
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2024-07-02 20:53:28 +00:00
|
|
|
// Grab the current hidden flag from the DB, in case we're editing an older, public revision of a filter that is
|
|
|
|
// currently hidden, so that we can also hide that public revision.
|
2019-01-18 11:01:32 +00:00
|
|
|
if (
|
2020-10-23 14:19:02 +00:00
|
|
|
( $filterObj->isHidden() || (
|
|
|
|
$filter !== null && $this->filterLookup->getFilter( $filter, false )->isHidden() )
|
|
|
|
) && !$this->afPermManager->canViewPrivateFilters( $user )
|
2019-03-28 19:59:53 +00:00
|
|
|
) {
|
2019-01-18 11:01:32 +00:00
|
|
|
$out->addHTML( $this->msg( 'abusefilter-edit-denied' )->escaped() );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:49:17 +00:00
|
|
|
// Filters that use protected variables should always be hidden from public view
|
2024-06-12 12:42:17 +00:00
|
|
|
if (
|
|
|
|
(
|
|
|
|
$filterObj->isProtected() ||
|
|
|
|
( $filter !== null && $this->filterLookup->getFilter( $filter, false )->isProtected() )
|
|
|
|
) &&
|
|
|
|
!$this->afPermManager->canViewProtectedVariables( $user )
|
|
|
|
) {
|
2024-05-23 14:49:17 +00:00
|
|
|
$out->addHTML( $this->msg( 'abusefilter-edit-denied-protected-vars' )->escaped() );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-12-10 13:14:27 +00:00
|
|
|
if ( $isCreatingNewFilter ) {
|
|
|
|
$title = $this->msg( 'abusefilter-add' );
|
|
|
|
} elseif ( $this->afPermManager->canEditFilter( $user, $filterObj ) ) {
|
|
|
|
$title = $this->msg( 'abusefilter-edit-specific' )
|
|
|
|
->numParams( $this->filter )
|
|
|
|
->params( $filterObj->getName() );
|
|
|
|
} else {
|
|
|
|
$title = $this->msg( 'abusefilter-view-specific' )
|
|
|
|
->numParams( $this->filter )
|
|
|
|
->params( $filterObj->getName() );
|
|
|
|
}
|
|
|
|
$out->setPageTitleMsg( $title );
|
|
|
|
|
2020-10-23 14:19:02 +00:00
|
|
|
$readOnly = !$this->afPermManager->canEditFilter( $user, $filterObj );
|
2020-09-18 14:49:13 +00:00
|
|
|
|
2019-01-18 11:01:32 +00:00
|
|
|
if ( $history_id ) {
|
2020-09-18 14:49:13 +00:00
|
|
|
$oldWarningMessage = $readOnly
|
|
|
|
? 'abusefilter-edit-oldwarning-view'
|
|
|
|
: 'abusefilter-edit-oldwarning';
|
2024-11-14 23:24:17 +00:00
|
|
|
$out->addWikiMsg( $oldWarningMessage, $history_id, (string)$filter );
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
|
2024-11-13 12:02:15 +00:00
|
|
|
if ( $status !== null && !$status->isGood() ) {
|
|
|
|
foreach ( $status->getMessages( 'error' ) as $message ) {
|
|
|
|
$out->addHTML( Html::errorBox( $this->msg( $message )->parseAsBlock() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ( $status->getMessages( 'warning' ) as $message ) {
|
|
|
|
$out->addHTML( Html::warningBox( $this->msg( $message )->parseAsBlock() ) );
|
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2017-06-15 14:23:16 +00:00
|
|
|
$fields = [];
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2010-02-13 14:10:36 +00:00
|
|
|
$fields['abusefilter-edit-id'] =
|
2023-12-10 13:14:27 +00:00
|
|
|
$isCreatingNewFilter ?
|
2018-05-01 12:13:57 +00:00
|
|
|
$this->msg( 'abusefilter-edit-new' )->escaped() :
|
2021-09-04 02:30:36 +00:00
|
|
|
htmlspecialchars( $lang->formatNum( (string)$filter ) );
|
2009-10-07 13:57:06 +00:00
|
|
|
$fields['abusefilter-edit-description'] =
|
2018-03-23 09:13:41 +00:00
|
|
|
new OOUI\TextInputWidget( [
|
|
|
|
'name' => 'wpFilterDescription',
|
2023-01-31 05:15:34 +00:00
|
|
|
'id' => 'mw-abusefilter-edit-description-input',
|
2020-09-20 14:50:37 +00:00
|
|
|
'value' => $filterObj->getName(),
|
2019-02-27 10:52:59 +00:00
|
|
|
'readOnly' => $readOnly
|
|
|
|
]
|
2009-02-07 09:34:11 +00:00
|
|
|
);
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2018-03-10 21:47:33 +00:00
|
|
|
$validGroups = $this->getConfig()->get( 'AbuseFilterValidGroups' );
|
|
|
|
if ( count( $validGroups ) > 1 ) {
|
2018-03-23 09:13:41 +00:00
|
|
|
$groupSelector =
|
|
|
|
new OOUI\DropdownInputWidget( [
|
|
|
|
'name' => 'wpFilterGroup',
|
|
|
|
'id' => 'mw-abusefilter-edit-group-input',
|
2020-09-20 14:50:37 +00:00
|
|
|
'value' => $filterObj->getGroup(),
|
2019-02-27 10:52:59 +00:00
|
|
|
'disabled' => $readOnly
|
2018-03-23 09:13:41 +00:00
|
|
|
] );
|
|
|
|
|
|
|
|
$options = [];
|
2018-03-10 21:47:33 +00:00
|
|
|
foreach ( $validGroups as $group ) {
|
2020-10-02 15:08:48 +00:00
|
|
|
$options += [ $this->specsFormatter->nameGroup( $group ) => $group ];
|
2012-05-06 06:44:45 +00:00
|
|
|
}
|
|
|
|
|
2024-05-04 08:14:01 +00:00
|
|
|
$options = Html::listDropdownOptionsOoui( $options );
|
2018-03-23 09:13:41 +00:00
|
|
|
$groupSelector->setOptions( $options );
|
2016-12-15 13:09:03 +00:00
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
$fields['abusefilter-edit-group'] = $groupSelector;
|
2012-05-06 06:44:45 +00:00
|
|
|
}
|
|
|
|
|
2009-01-23 19:23:19 +00:00
|
|
|
// Hit count display
|
2024-10-26 19:41:16 +00:00
|
|
|
$hitCount = $filterObj->getHitCount();
|
|
|
|
if ( $hitCount !== null && $this->afPermManager->canSeeLogDetails( $user ) ) {
|
2012-09-02 11:07:02 +00:00
|
|
|
$count_display = $this->msg( 'abusefilter-hitcount' )
|
2024-10-26 19:41:16 +00:00
|
|
|
->numParams( $hitCount )->text();
|
2016-12-04 15:13:16 +00:00
|
|
|
$hitCount = $this->linkRenderer->makeKnownLink(
|
2009-10-07 13:57:06 +00:00
|
|
|
SpecialPage::getTitleFor( 'AbuseLog' ),
|
|
|
|
$count_display,
|
2017-06-15 14:23:16 +00:00
|
|
|
[],
|
2020-09-20 14:50:37 +00:00
|
|
|
[ 'wpSearchFilter' => $filterObj->getID() ]
|
2009-10-07 13:57:06 +00:00
|
|
|
);
|
2009-01-23 19:23:19 +00:00
|
|
|
|
|
|
|
$fields['abusefilter-edit-hitcount'] = $hitCount;
|
|
|
|
}
|
|
|
|
|
2020-09-20 14:50:37 +00:00
|
|
|
if ( $filter !== null && $filterObj->isEnabled() ) {
|
2009-01-23 19:23:19 +00:00
|
|
|
// Statistics
|
2020-10-27 09:17:37 +00:00
|
|
|
[
|
|
|
|
'count' => $totalCount,
|
|
|
|
'matches' => $matchesCount,
|
|
|
|
'total-time' => $curTotalTime,
|
|
|
|
'total-cond' => $curTotalConds,
|
2020-10-23 14:19:02 +00:00
|
|
|
] = $this->filterProfiler->getFilterProfile( $filter );
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2019-02-10 10:57:37 +00:00
|
|
|
if ( $totalCount > 0 ) {
|
|
|
|
$matchesPercent = round( 100 * $matchesCount / $totalCount, 2 );
|
2020-10-27 09:17:37 +00:00
|
|
|
$avgTime = round( $curTotalTime / $totalCount, 2 );
|
|
|
|
$avgCond = round( $curTotalConds / $totalCount, 1 );
|
|
|
|
|
2019-01-24 12:33:31 +00:00
|
|
|
$fields['abusefilter-edit-status-label'] = $this->msg( 'abusefilter-edit-status' )
|
2019-02-10 10:57:37 +00:00
|
|
|
->numParams( $totalCount, $matchesCount, $matchesPercent, $avgTime, $avgCond )
|
2019-03-29 08:54:30 +00:00
|
|
|
->parse();
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-23 14:19:02 +00:00
|
|
|
$boxBuilder = $this->boxBuilderFactory->newEditBoxBuilder( $this, $user, $out );
|
2020-11-24 12:16:41 +00:00
|
|
|
|
|
|
|
$fields['abusefilter-edit-rules'] = $boxBuilder->buildEditBox(
|
2020-09-20 14:50:37 +00:00
|
|
|
$filterObj->getRules(),
|
2018-04-08 15:57:23 +00:00
|
|
|
true
|
2012-09-02 11:07:02 +00:00
|
|
|
);
|
2018-03-23 09:13:41 +00:00
|
|
|
$fields['abusefilter-edit-notes'] =
|
|
|
|
new OOUI\MultilineTextInputWidget( [
|
|
|
|
'name' => 'wpFilterNotes',
|
2020-09-20 14:50:37 +00:00
|
|
|
'value' => $filterObj->getComments() . "\n",
|
2019-02-27 10:52:59 +00:00
|
|
|
'rows' => 15,
|
2019-08-17 16:53:13 +00:00
|
|
|
'readOnly' => $readOnly,
|
|
|
|
'id' => 'mw-abusefilter-notes-editor'
|
|
|
|
] );
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2018-03-09 12:20:33 +00:00
|
|
|
// Build checkboxes
|
2024-11-13 12:10:20 +00:00
|
|
|
$checkboxes = [ 'hidden', 'enabled', 'deleted' ];
|
2009-01-23 19:23:19 +00:00
|
|
|
$flags = '';
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2024-11-13 12:10:20 +00:00
|
|
|
// Show the 'protected' check box either to indicate that the filter is protected, or
|
|
|
|
// to allow a user to protect the filter, if the filter needs to be protected.
|
|
|
|
if (
|
|
|
|
$filterObj->isProtected() ||
|
|
|
|
(
|
|
|
|
$status !== null &&
|
|
|
|
$status->hasMessage( 'abusefilter-edit-protected-variable-not-protected' )
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
$checkboxes[] = 'protected';
|
|
|
|
}
|
|
|
|
|
2018-03-10 21:47:33 +00:00
|
|
|
if ( $this->getConfig()->get( 'AbuseFilterIsCentral' ) ) {
|
2009-03-30 06:12:12 +00:00
|
|
|
$checkboxes[] = 'global';
|
2010-08-19 21:12:09 +00:00
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2020-09-20 14:50:37 +00:00
|
|
|
if ( $filterObj->isThrottled() ) {
|
2022-02-19 13:49:58 +00:00
|
|
|
$throttledActionNames = array_intersect(
|
2020-09-20 14:50:37 +00:00
|
|
|
$filterObj->getActionsNames(),
|
2020-11-29 22:55:34 +00:00
|
|
|
$this->consequencesRegistry->getDangerousActionNames()
|
2015-09-28 18:03:35 +00:00
|
|
|
);
|
2012-10-23 13:14:34 +00:00
|
|
|
|
2022-02-19 13:49:58 +00:00
|
|
|
if ( $throttledActionNames ) {
|
|
|
|
$throttledActionsLocalized = [];
|
|
|
|
foreach ( $throttledActionNames as $actionName ) {
|
|
|
|
$throttledActionsLocalized[] = $this->specsFormatter->getActionMessage( $actionName )->text();
|
|
|
|
}
|
|
|
|
|
|
|
|
$throttledMsg = $this->msg( 'abusefilter-edit-throttled-warning' )
|
|
|
|
->plaintextParams( $lang->commaList( $throttledActionsLocalized ) )
|
|
|
|
->params( count( $throttledActionsLocalized ) )
|
|
|
|
->parseAsBlock();
|
|
|
|
} else {
|
|
|
|
$throttledMsg = $this->msg( 'abusefilter-edit-throttled-warning-no-actions' )
|
|
|
|
->parseAsBlock();
|
2017-09-05 20:11:18 +00:00
|
|
|
}
|
2022-02-19 13:49:58 +00:00
|
|
|
$flags .= Html::warningBox( $throttledMsg );
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
|
2010-02-13 14:10:36 +00:00
|
|
|
foreach ( $checkboxes as $checkboxId ) {
|
2012-09-04 08:37:12 +00:00
|
|
|
// Messages that can be used here:
|
|
|
|
// * abusefilter-edit-enabled
|
|
|
|
// * abusefilter-edit-deleted
|
|
|
|
// * abusefilter-edit-hidden
|
2024-06-04 13:47:16 +00:00
|
|
|
// * abusefilter-edit-protected
|
2012-09-04 08:37:12 +00:00
|
|
|
// * abusefilter-edit-global
|
2009-01-23 19:23:19 +00:00
|
|
|
$message = "abusefilter-edit-$checkboxId";
|
2024-06-04 13:47:16 +00:00
|
|
|
// isEnabled(), isDeleted(), isHidden(), isProtected(), isGlobal()
|
2020-09-20 14:50:37 +00:00
|
|
|
$method = 'is' . ucfirst( $checkboxId );
|
2024-10-29 03:10:27 +00:00
|
|
|
// wpFilterEnabled, wpFilterDeleted, wpFilterHidden, wpFilterProtected, wpFilterGlobal
|
2009-10-07 13:57:06 +00:00
|
|
|
$postVar = 'wpFilter' . ucfirst( $checkboxId );
|
2018-03-23 09:13:41 +00:00
|
|
|
|
|
|
|
$checkboxAttribs = [
|
|
|
|
'name' => $postVar,
|
|
|
|
'id' => $postVar,
|
2020-09-20 14:50:37 +00:00
|
|
|
'selected' => $filterObj->$method(),
|
2019-02-27 10:52:59 +00:00
|
|
|
'disabled' => $readOnly
|
|
|
|
];
|
2018-03-23 09:13:41 +00:00
|
|
|
$labelAttribs = [
|
|
|
|
'label' => $this->msg( $message )->text(),
|
|
|
|
'align' => 'inline',
|
|
|
|
];
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2020-10-23 14:19:02 +00:00
|
|
|
if ( $checkboxId === 'global' && !$this->afPermManager->canEditGlobal( $user ) ) {
|
2018-03-23 09:13:41 +00:00
|
|
|
$checkboxAttribs['disabled'] = 'disabled';
|
2012-09-12 15:31:24 +00:00
|
|
|
}
|
|
|
|
|
2024-06-05 16:45:12 +00:00
|
|
|
if ( $checkboxId == 'protected' ) {
|
2024-11-13 12:10:20 +00:00
|
|
|
if ( $filterObj->isProtected() ) {
|
2024-06-05 16:45:12 +00:00
|
|
|
$checkboxAttribs['disabled'] = true;
|
|
|
|
$labelAttribs['label'] = $this->msg(
|
|
|
|
'abusefilter-edit-protected-variable-already-protected'
|
|
|
|
)->text();
|
|
|
|
} else {
|
|
|
|
$labelAttribs['label'] = new OOUI\HtmlSnippet(
|
|
|
|
$this->msg( $message )->parse()
|
|
|
|
);
|
|
|
|
$labelAttribs['help'] = $this->msg( 'abusefilter-edit-protected-help-message' )->text();
|
|
|
|
$labelAttribs['helpInline'] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-02 16:59:55 +00:00
|
|
|
// Set readonly on deleted if the filter isn't disabled
|
2020-09-20 14:50:37 +00:00
|
|
|
if ( $checkboxId === 'deleted' && $filterObj->isEnabled() ) {
|
2018-03-23 09:13:41 +00:00
|
|
|
$checkboxAttribs['disabled'] = 'disabled';
|
2018-05-02 16:59:55 +00:00
|
|
|
}
|
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
// Add infusable where needed
|
2018-08-26 08:34:42 +00:00
|
|
|
if ( $checkboxId === 'deleted' || $checkboxId === 'enabled' ) {
|
2018-03-23 09:13:41 +00:00
|
|
|
$checkboxAttribs['infusable'] = true;
|
2018-08-26 08:34:42 +00:00
|
|
|
if ( $checkboxId === 'deleted' ) {
|
2024-10-29 03:10:27 +00:00
|
|
|
// wpFilterDeletedLabel
|
2018-03-23 09:13:41 +00:00
|
|
|
$labelAttribs['id'] = $postVar . 'Label';
|
|
|
|
$labelAttribs['infusable'] = true;
|
|
|
|
}
|
|
|
|
}
|
2018-05-05 12:35:01 +00:00
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
$checkbox =
|
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\CheckboxInputWidget( $checkboxAttribs ),
|
|
|
|
$labelAttribs
|
|
|
|
);
|
2009-01-23 19:23:19 +00:00
|
|
|
$flags .= $checkbox;
|
|
|
|
}
|
2010-02-13 14:10:36 +00:00
|
|
|
|
2009-01-23 19:23:19 +00:00
|
|
|
$fields['abusefilter-edit-flags'] = $flags;
|
2010-02-13 14:10:36 +00:00
|
|
|
|
2020-09-20 10:18:46 +00:00
|
|
|
if ( $filter !== null ) {
|
2019-08-21 15:32:43 +00:00
|
|
|
$tools = '';
|
2020-10-23 14:19:02 +00:00
|
|
|
if ( $this->afPermManager->canRevertFilterActions( $user ) ) {
|
2024-03-29 12:40:23 +00:00
|
|
|
$tools .= Html::rawElement(
|
|
|
|
'p', [],
|
2016-12-16 20:08:52 +00:00
|
|
|
$this->linkRenderer->makeLink(
|
|
|
|
$this->getTitle( "revert/$filter" ),
|
2017-02-05 21:56:39 +00:00
|
|
|
new HtmlArmor( $this->msg( 'abusefilter-edit-revert' )->parse() )
|
2016-12-16 20:08:52 +00:00
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-02-19 17:50:38 +00:00
|
|
|
if ( $this->afPermManager->canUseTestTools( $user ) ) {
|
2016-12-16 20:08:52 +00:00
|
|
|
// Test link
|
2024-03-29 12:40:23 +00:00
|
|
|
$tools .= Html::rawElement(
|
|
|
|
'p', [],
|
2016-12-16 20:08:52 +00:00
|
|
|
$this->linkRenderer->makeLink(
|
|
|
|
$this->getTitle( "test/$filter" ),
|
|
|
|
new HtmlArmor( $this->msg( 'abusefilter-edit-test-link' )->parse() )
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
// Last modification details
|
2009-10-07 13:57:06 +00:00
|
|
|
$userLink =
|
2020-09-20 14:50:37 +00:00
|
|
|
Linker::userLink( $filterObj->getUserID(), $filterObj->getUserName() ) .
|
|
|
|
Linker::userToolLinks( $filterObj->getUserID(), $filterObj->getUserName() );
|
2009-10-07 13:57:06 +00:00
|
|
|
$fields['abusefilter-edit-lastmod'] =
|
2012-09-02 11:07:02 +00:00
|
|
|
$this->msg( 'abusefilter-edit-lastmod-text' )
|
2016-01-21 09:57:56 +00:00
|
|
|
->rawParams(
|
|
|
|
$this->getLinkToLatestDiff(
|
|
|
|
$filter,
|
2021-03-08 23:54:03 +00:00
|
|
|
$lang->userTimeAndDate( $filterObj->getTimestamp(), $user )
|
2016-01-21 09:57:56 +00:00
|
|
|
),
|
|
|
|
$userLink,
|
|
|
|
$this->getLinkToLatestDiff(
|
|
|
|
$filter,
|
2021-03-08 23:54:03 +00:00
|
|
|
$lang->userDate( $filterObj->getTimestamp(), $user )
|
2016-01-21 09:57:56 +00:00
|
|
|
),
|
|
|
|
$this->getLinkToLatestDiff(
|
|
|
|
$filter,
|
2021-03-08 23:54:03 +00:00
|
|
|
$lang->userTime( $filterObj->getTimestamp(), $user )
|
2016-01-21 09:57:56 +00:00
|
|
|
)
|
2018-07-04 15:04:05 +00:00
|
|
|
)->params(
|
2020-09-20 14:50:37 +00:00
|
|
|
wfEscapeWikiText( $filterObj->getUserName() )
|
2012-09-02 11:07:02 +00:00
|
|
|
)->parse();
|
2016-12-04 15:13:16 +00:00
|
|
|
$history_display = new HtmlArmor( $this->msg( 'abusefilter-edit-viewhistory' )->parse() );
|
2009-10-07 13:57:06 +00:00
|
|
|
$fields['abusefilter-edit-history'] =
|
2016-12-04 15:13:16 +00:00
|
|
|
$this->linkRenderer->makeKnownLink( $this->getTitle( 'history/' . $filter ), $history_display );
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-10-23 14:19:02 +00:00
|
|
|
$exportText = $this->filterImporter->encodeData( $filterObj, $actions );
|
2024-03-29 12:40:23 +00:00
|
|
|
$tools .= Html::rawElement( 'a', [ 'href' => '#', 'id' => 'mw-abusefilter-export-link' ],
|
2019-08-11 10:21:36 +00:00
|
|
|
$this->msg( 'abusefilter-edit-export' )->parse() );
|
|
|
|
$tools .=
|
|
|
|
new OOUI\MultilineTextInputWidget( [
|
|
|
|
'id' => 'mw-abusefilter-export',
|
|
|
|
'readOnly' => true,
|
|
|
|
'value' => $exportText,
|
|
|
|
'rows' => 10
|
|
|
|
] );
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2019-08-21 15:32:43 +00:00
|
|
|
$fields['abusefilter-edit-tools'] = $tools;
|
|
|
|
}
|
2009-01-30 19:30:51 +00:00
|
|
|
|
2024-03-29 12:40:23 +00:00
|
|
|
$form = Xml::fieldset(
|
|
|
|
$this->msg( 'abusefilter-edit-main' )->text(),
|
|
|
|
// TODO: deprecated, use OOUI or Codex widgets instead
|
|
|
|
Xml::buildForm( $fields )
|
|
|
|
);
|
2009-10-07 13:57:06 +00:00
|
|
|
$form .= Xml::fieldset(
|
2012-09-02 11:07:02 +00:00
|
|
|
$this->msg( 'abusefilter-edit-consequences' )->text(),
|
2020-09-20 14:50:37 +00:00
|
|
|
$this->buildConsequenceEditor( $filterObj, $actions )
|
2009-02-07 09:34:11 +00:00
|
|
|
);
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2020-11-17 22:19:18 +00:00
|
|
|
$urlFilter = $filter === null ? 'new' : (string)$filter;
|
2020-09-18 14:49:13 +00:00
|
|
|
if ( !$readOnly ) {
|
2018-03-23 09:13:41 +00:00
|
|
|
$form .=
|
|
|
|
new OOUI\ButtonInputWidget( [
|
|
|
|
'type' => 'submit',
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-save' )->text(),
|
|
|
|
'useInputTag' => true,
|
|
|
|
'accesskey' => 's',
|
|
|
|
'flags' => [ 'progressive', 'primary' ]
|
|
|
|
] );
|
2010-10-29 15:32:44 +00:00
|
|
|
$form .= Html::hidden(
|
2010-02-13 14:10:36 +00:00
|
|
|
'wpEditToken',
|
2024-05-04 08:14:01 +00:00
|
|
|
$this->getCsrfTokenSet()->getToken( [ 'abusefilter', $urlFilter ] )->toString()
|
2009-02-07 09:34:11 +00:00
|
|
|
);
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
|
2024-03-29 12:40:23 +00:00
|
|
|
$form = Html::rawElement( 'form',
|
2017-06-15 14:23:16 +00:00
|
|
|
[
|
2020-09-20 10:18:46 +00:00
|
|
|
'action' => $this->getTitle( $urlFilter )->getFullURL(),
|
2018-12-04 12:06:46 +00:00
|
|
|
'method' => 'post',
|
|
|
|
'id' => 'mw-abusefilter-editing-form'
|
2017-06-15 14:23:16 +00:00
|
|
|
],
|
2009-10-07 13:57:06 +00:00
|
|
|
$form
|
|
|
|
);
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2019-01-18 11:01:32 +00:00
|
|
|
$out->addHTML( $form );
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2019-01-18 11:01:32 +00:00
|
|
|
if ( $history_id ) {
|
2024-04-10 23:07:29 +00:00
|
|
|
// @phan-suppress-next-line PhanPossiblyUndeclaredVariable,PhanTypeMismatchArgumentNullable
|
2019-11-04 18:26:53 +00:00
|
|
|
$out->addWikiMsg( $oldWarningMessage, $history_id, $filter );
|
2019-01-18 11:01:32 +00:00
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
|
2012-03-11 20:51:54 +00:00
|
|
|
/**
|
2012-05-06 05:59:35 +00:00
|
|
|
* Builds the "actions" editor for a given filter.
|
2020-09-20 14:50:37 +00:00
|
|
|
* @param Filter $filterObj
|
2019-08-17 15:51:44 +00:00
|
|
|
* @param array[] $actions Array of rows from the abuse_filter_action table
|
2020-09-20 14:50:37 +00:00
|
|
|
* corresponding to the filter object
|
2018-04-29 17:52:45 +00:00
|
|
|
* @return string HTML text for an action editor.
|
2012-03-11 20:51:54 +00:00
|
|
|
*/
|
2020-09-20 14:50:37 +00:00
|
|
|
private function buildConsequenceEditor( Filter $filterObj, array $actions ) {
|
2020-11-29 23:10:14 +00:00
|
|
|
$enabledActions = $this->consequencesRegistry->getAllEnabledActionNames();
|
2010-02-13 14:10:36 +00:00
|
|
|
|
2017-06-15 14:23:16 +00:00
|
|
|
$setActions = [];
|
2020-11-29 23:10:14 +00:00
|
|
|
foreach ( $enabledActions as $action ) {
|
2009-01-23 19:23:19 +00:00
|
|
|
$setActions[$action] = array_key_exists( $action, $actions );
|
|
|
|
}
|
|
|
|
|
|
|
|
$output = '';
|
|
|
|
|
2020-11-29 23:10:14 +00:00
|
|
|
foreach ( $enabledActions as $action ) {
|
2019-10-23 16:44:06 +00:00
|
|
|
$params = $actions[$action] ?? null;
|
|
|
|
$output .= $this->buildConsequenceSelector(
|
2020-09-20 14:50:37 +00:00
|
|
|
$action, $setActions[$action], $filterObj, $params );
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
|
2009-01-23 19:23:44 +00:00
|
|
|
return $output;
|
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2012-03-11 20:51:54 +00:00
|
|
|
/**
|
2017-10-06 18:52:31 +00:00
|
|
|
* @param string $action The action to build an editor for
|
|
|
|
* @param bool $set Whether or not the action is activated
|
2020-09-20 14:50:37 +00:00
|
|
|
* @param Filter $filterObj
|
2019-12-07 17:20:10 +00:00
|
|
|
* @param string[]|null $parameters Action parameters. Null iff $set is false.
|
2018-10-03 12:02:00 +00:00
|
|
|
* @return string|\OOUI\FieldLayout
|
2012-03-11 20:51:54 +00:00
|
|
|
*/
|
2020-09-20 14:50:37 +00:00
|
|
|
private function buildConsequenceSelector( $action, $set, $filterObj, ?array $parameters ) {
|
2018-03-10 21:47:33 +00:00
|
|
|
$config = $this->getConfig();
|
2019-08-27 09:40:01 +00:00
|
|
|
$user = $this->getUser();
|
2020-11-29 23:10:14 +00:00
|
|
|
$actions = $this->consequencesRegistry->getAllEnabledActionNames();
|
|
|
|
if ( !in_array( $action, $actions, true ) ) {
|
2019-10-23 16:44:06 +00:00
|
|
|
return '';
|
|
|
|
}
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-10-23 14:19:02 +00:00
|
|
|
$readOnly = !$this->afPermManager->canEditFilter( $user, $filterObj );
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2015-09-28 18:03:35 +00:00
|
|
|
switch ( $action ) {
|
2009-01-23 19:23:44 +00:00
|
|
|
case 'throttle':
|
2013-10-28 05:47:14 +00:00
|
|
|
// Throttling is only available via object caching
|
2023-06-12 08:27:03 +00:00
|
|
|
if ( $config->get( MainConfigNames::MainCacheType ) === CACHE_NONE ) {
|
2013-10-28 05:47:14 +00:00
|
|
|
return '';
|
|
|
|
}
|
2018-03-23 09:13:41 +00:00
|
|
|
$throttleSettings =
|
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\CheckboxInputWidget( [
|
|
|
|
'name' => 'wpFilterActionThrottle',
|
|
|
|
'id' => 'mw-abusefilter-action-checkbox-throttle',
|
|
|
|
'selected' => $set,
|
2019-02-27 10:52:59 +00:00
|
|
|
'classes' => [ 'mw-abusefilter-action-checkbox' ],
|
|
|
|
'disabled' => $readOnly
|
|
|
|
]
|
2018-03-23 09:13:41 +00:00
|
|
|
),
|
|
|
|
[
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-action-throttle' )->text(),
|
|
|
|
'align' => 'inline'
|
|
|
|
]
|
|
|
|
);
|
2017-06-15 14:23:16 +00:00
|
|
|
$throttleFields = [];
|
2009-01-23 19:23:44 +00:00
|
|
|
|
2009-10-07 13:57:06 +00:00
|
|
|
if ( $set ) {
|
2019-10-23 16:44:06 +00:00
|
|
|
// @phan-suppress-next-line PhanTypeArraySuspiciousNullable $parameters is array here
|
2024-03-16 18:52:48 +00:00
|
|
|
[ $throttleCount, $throttlePeriod ] = explode( ',', $parameters[1], 2 );
|
2009-01-23 19:23:44 +00:00
|
|
|
|
2019-05-15 14:14:12 +00:00
|
|
|
$throttleGroups = array_slice( $parameters, 2 );
|
2009-01-23 19:23:44 +00:00
|
|
|
} else {
|
|
|
|
$throttleCount = 3;
|
|
|
|
$throttlePeriod = 60;
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
$throttleGroups = [ 'user' ];
|
2009-01-23 19:23:44 +00:00
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2022-01-13 15:37:04 +00:00
|
|
|
$throttleFields[] =
|
2018-03-23 09:13:41 +00:00
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\TextInputWidget( [
|
|
|
|
'type' => 'number',
|
|
|
|
'name' => 'wpFilterThrottleCount',
|
2019-02-27 10:52:59 +00:00
|
|
|
'value' => $throttleCount,
|
|
|
|
'readOnly' => $readOnly
|
|
|
|
]
|
2018-03-23 09:13:41 +00:00
|
|
|
),
|
|
|
|
[
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-throttle-count' )->text()
|
|
|
|
]
|
|
|
|
);
|
2022-01-13 15:37:04 +00:00
|
|
|
$throttleFields[] =
|
2018-03-23 09:13:41 +00:00
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\TextInputWidget( [
|
|
|
|
'type' => 'number',
|
|
|
|
'name' => 'wpFilterThrottlePeriod',
|
2019-02-27 10:52:59 +00:00
|
|
|
'value' => $throttlePeriod,
|
|
|
|
'readOnly' => $readOnly
|
|
|
|
]
|
2018-03-23 09:13:41 +00:00
|
|
|
),
|
|
|
|
[
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-throttle-period' )->text()
|
|
|
|
]
|
|
|
|
);
|
2018-09-09 10:14:31 +00:00
|
|
|
|
2019-03-18 09:51:53 +00:00
|
|
|
$groupsHelpLink = Html::element(
|
|
|
|
'a',
|
|
|
|
[
|
|
|
|
'href' => 'https://www.mediawiki.org/wiki/Special:MyLanguage/' .
|
|
|
|
'Extension:AbuseFilter/Actions#Throttling',
|
|
|
|
'target' => '_blank'
|
|
|
|
],
|
|
|
|
$this->msg( 'abusefilter-edit-throttle-groups-help-text' )->text()
|
|
|
|
);
|
|
|
|
$groupsHelp = $this->msg( 'abusefilter-edit-throttle-groups-help' )
|
|
|
|
->rawParams( $groupsHelpLink )->escaped();
|
2018-09-09 10:14:31 +00:00
|
|
|
$hiddenGroups =
|
2018-03-23 09:13:41 +00:00
|
|
|
new OOUI\FieldLayout(
|
2018-09-09 10:14:31 +00:00
|
|
|
new OOUI\MultilineTextInputWidget( [
|
|
|
|
'name' => 'wpFilterThrottleGroups',
|
|
|
|
'value' => implode( "\n", $throttleGroups ),
|
|
|
|
'rows' => 5,
|
|
|
|
'placeholder' => $this->msg( 'abusefilter-edit-throttle-hidden-placeholder' )->text(),
|
|
|
|
'infusable' => true,
|
2019-02-27 10:52:59 +00:00
|
|
|
'id' => 'mw-abusefilter-hidden-throttle-field',
|
|
|
|
'readOnly' => $readOnly
|
|
|
|
]
|
2018-09-09 10:14:31 +00:00
|
|
|
),
|
2018-03-23 09:13:41 +00:00
|
|
|
[
|
2018-09-09 10:14:31 +00:00
|
|
|
'label' => new OOUI\HtmlSnippet(
|
|
|
|
$this->msg( 'abusefilter-edit-throttle-groups' )->parse()
|
|
|
|
),
|
|
|
|
'align' => 'top',
|
2019-01-24 11:58:41 +00:00
|
|
|
'id' => 'mw-abusefilter-hidden-throttle',
|
2019-03-18 09:51:53 +00:00
|
|
|
'help' => new OOUI\HtmlSnippet( $groupsHelp ),
|
2019-01-24 11:58:41 +00:00
|
|
|
'helpInline' => true
|
2018-03-23 09:13:41 +00:00
|
|
|
]
|
|
|
|
);
|
2018-09-09 10:14:31 +00:00
|
|
|
|
2022-01-13 15:37:04 +00:00
|
|
|
$throttleFields[] = $hiddenGroups;
|
2018-09-09 10:14:31 +00:00
|
|
|
|
2019-03-18 09:51:53 +00:00
|
|
|
$throttleConfig = [
|
|
|
|
'values' => $throttleGroups,
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-throttle-groups' )->parse(),
|
|
|
|
'disabled' => $readOnly,
|
|
|
|
'help' => $groupsHelp
|
|
|
|
];
|
|
|
|
$this->getOutput()->addJsConfigVars( 'throttleConfig', $throttleConfig );
|
|
|
|
|
2009-10-07 13:57:06 +00:00
|
|
|
$throttleSettings .=
|
2024-03-29 12:40:23 +00:00
|
|
|
Html::rawElement(
|
2009-10-07 13:57:06 +00:00
|
|
|
'div',
|
2017-06-15 14:23:16 +00:00
|
|
|
[ 'id' => 'mw-abusefilter-throttle-parameters' ],
|
2018-03-23 09:13:41 +00:00
|
|
|
new OOUI\FieldsetLayout( [ 'items' => $throttleFields ] )
|
2009-02-07 09:34:11 +00:00
|
|
|
);
|
2009-01-28 19:40:15 +00:00
|
|
|
return $throttleSettings;
|
2014-10-04 14:42:46 +00:00
|
|
|
case 'disallow':
|
2009-01-23 19:23:44 +00:00
|
|
|
case 'warn':
|
|
|
|
$output = '';
|
2014-10-04 14:42:46 +00:00
|
|
|
$formName = $action === 'warn' ? 'wpFilterActionWarn' : 'wpFilterActionDisallow';
|
2018-03-23 09:13:41 +00:00
|
|
|
$checkbox =
|
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\CheckboxInputWidget( [
|
2014-10-04 14:42:46 +00:00
|
|
|
'name' => $formName,
|
|
|
|
// mw-abusefilter-action-checkbox-warn, mw-abusefilter-action-checkbox-disallow
|
|
|
|
'id' => "mw-abusefilter-action-checkbox-$action",
|
2018-03-23 09:13:41 +00:00
|
|
|
'selected' => $set,
|
2019-02-27 10:52:59 +00:00
|
|
|
'classes' => [ 'mw-abusefilter-action-checkbox' ],
|
|
|
|
'disabled' => $readOnly
|
|
|
|
]
|
2018-03-23 09:13:41 +00:00
|
|
|
),
|
|
|
|
[
|
2014-10-04 14:42:46 +00:00
|
|
|
// abusefilter-edit-action-warn, abusefilter-edit-action-disallow
|
|
|
|
'label' => $this->msg( "abusefilter-edit-action-$action" )->text(),
|
2018-03-23 09:13:41 +00:00
|
|
|
'align' => 'inline'
|
|
|
|
]
|
|
|
|
);
|
|
|
|
$output .= $checkbox;
|
2014-10-04 14:42:46 +00:00
|
|
|
$defaultWarnMsg = $config->get( 'AbuseFilterDefaultWarningMessage' );
|
|
|
|
$defaultDisallowMsg = $config->get( 'AbuseFilterDefaultDisallowMessage' );
|
|
|
|
|
|
|
|
if ( $set && isset( $parameters[0] ) ) {
|
|
|
|
$msg = $parameters[0];
|
2012-06-06 05:18:31 +00:00
|
|
|
} elseif (
|
2020-09-20 14:50:37 +00:00
|
|
|
( $action === 'warn' && isset( $defaultWarnMsg[$filterObj->getGroup()] ) ) ||
|
|
|
|
( $action === 'disallow' && isset( $defaultDisallowMsg[$filterObj->getGroup()] ) )
|
2012-06-06 05:18:31 +00:00
|
|
|
) {
|
2020-09-20 14:50:37 +00:00
|
|
|
$msg = $action === 'warn' ? $defaultWarnMsg[$filterObj->getGroup()] :
|
|
|
|
$defaultDisallowMsg[$filterObj->getGroup()];
|
2012-06-06 05:18:31 +00:00
|
|
|
} else {
|
2014-10-04 14:42:46 +00:00
|
|
|
$msg = $action === 'warn' ? 'abusefilter-warning' : 'abusefilter-disallowed';
|
2012-06-06 05:18:31 +00:00
|
|
|
}
|
2009-02-03 22:45:42 +00:00
|
|
|
|
2018-10-03 15:55:06 +00:00
|
|
|
$fields = [];
|
2022-01-13 15:37:04 +00:00
|
|
|
$fields[] =
|
2019-02-27 10:52:59 +00:00
|
|
|
$this->getExistingSelector( $msg, $readOnly, $action );
|
2014-10-04 14:42:46 +00:00
|
|
|
$otherFieldName = $action === 'warn' ? 'wpFilterWarnMessageOther'
|
|
|
|
: 'wpFilterDisallowMessageOther';
|
|
|
|
|
2022-01-13 15:37:04 +00:00
|
|
|
$fields[] =
|
2018-03-23 09:13:41 +00:00
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\TextInputWidget( [
|
2014-10-04 14:42:46 +00:00
|
|
|
'name' => $otherFieldName,
|
|
|
|
'value' => $msg,
|
|
|
|
// mw-abusefilter-warn-message-other, mw-abusefilter-disallow-message-other
|
|
|
|
'id' => "mw-abusefilter-$action-message-other",
|
2019-02-27 10:52:59 +00:00
|
|
|
'infusable' => true,
|
|
|
|
'readOnly' => $readOnly
|
|
|
|
]
|
2018-03-23 09:13:41 +00:00
|
|
|
),
|
|
|
|
[
|
|
|
|
'label' => new OOUI\HtmlSnippet(
|
2014-10-04 14:42:46 +00:00
|
|
|
// abusefilter-edit-warn-other-label, abusefilter-edit-disallow-other-label
|
|
|
|
$this->msg( "abusefilter-edit-$action-other-label" )->parse()
|
2018-03-23 09:13:41 +00:00
|
|
|
)
|
|
|
|
]
|
2009-02-07 09:34:11 +00:00
|
|
|
);
|
2009-02-03 22:45:42 +00:00
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
$previewButton =
|
|
|
|
new OOUI\ButtonInputWidget( [
|
2014-10-04 14:42:46 +00:00
|
|
|
// abusefilter-edit-warn-preview, abusefilter-edit-disallow-preview
|
|
|
|
'label' => $this->msg( "abusefilter-edit-$action-preview" )->text(),
|
|
|
|
// mw-abusefilter-warn-preview-button, mw-abusefilter-disallow-preview-button
|
|
|
|
'id' => "mw-abusefilter-$action-preview-button",
|
2018-03-23 09:13:41 +00:00
|
|
|
'infusable' => true,
|
|
|
|
'flags' => 'progressive'
|
2016-12-15 13:09:03 +00:00
|
|
|
]
|
|
|
|
);
|
2018-03-23 09:13:41 +00:00
|
|
|
|
|
|
|
$buttonGroup = $previewButton;
|
2020-10-23 14:19:02 +00:00
|
|
|
if ( $this->permissionManager->userHasRight( $user, 'editinterface' ) ) {
|
2018-03-23 09:13:41 +00:00
|
|
|
$editButton =
|
|
|
|
new OOUI\ButtonInputWidget( [
|
2014-10-04 14:42:46 +00:00
|
|
|
// abusefilter-edit-warn-edit, abusefilter-edit-disallow-edit
|
|
|
|
'label' => $this->msg( "abusefilter-edit-$action-edit" )->text(),
|
|
|
|
// mw-abusefilter-warn-edit-button, mw-abusefilter-disallow-edit-button
|
|
|
|
'id' => "mw-abusefilter-$action-edit-button"
|
2018-03-23 09:13:41 +00:00
|
|
|
]
|
|
|
|
);
|
|
|
|
$buttonGroup =
|
|
|
|
new OOUI\Widget( [
|
|
|
|
'content' =>
|
|
|
|
new OOUI\HorizontalLayout( [
|
|
|
|
'items' => [ $previewButton, $editButton ],
|
|
|
|
'classes' => [
|
2014-10-04 14:42:46 +00:00
|
|
|
'mw-abusefilter-preview-buttons',
|
2018-03-23 09:13:41 +00:00
|
|
|
'mw-abusefilter-javascript-tools'
|
|
|
|
]
|
|
|
|
] )
|
|
|
|
] );
|
2016-12-15 13:09:03 +00:00
|
|
|
}
|
2024-03-29 12:40:23 +00:00
|
|
|
$previewHolder = Html::rawElement(
|
2009-10-07 13:57:06 +00:00
|
|
|
'div',
|
2014-10-04 14:42:46 +00:00
|
|
|
[
|
|
|
|
// mw-abusefilter-warn-preview, mw-abusefilter-disallow-preview
|
|
|
|
'id' => "mw-abusefilter-$action-preview",
|
|
|
|
'style' => 'display:none'
|
|
|
|
],
|
2018-03-23 09:13:41 +00:00
|
|
|
''
|
2009-02-07 09:34:11 +00:00
|
|
|
);
|
2022-01-13 15:37:04 +00:00
|
|
|
$fields[] = $buttonGroup;
|
2009-10-07 13:57:06 +00:00
|
|
|
$output .=
|
2024-03-29 12:40:23 +00:00
|
|
|
Html::rawElement(
|
2009-10-07 13:57:06 +00:00
|
|
|
'div',
|
2014-10-04 14:42:46 +00:00
|
|
|
// mw-abusefilter-warn-parameters, mw-abusefilter-disallow-parameters
|
|
|
|
[ 'id' => "mw-abusefilter-$action-parameters" ],
|
|
|
|
new OOUI\FieldsetLayout( [ 'items' => $fields ] )
|
2018-03-23 09:13:41 +00:00
|
|
|
) . $previewHolder;
|
|
|
|
|
2009-01-23 19:23:44 +00:00
|
|
|
return $output;
|
2009-01-28 19:08:18 +00:00
|
|
|
case 'tag':
|
2019-12-07 17:20:10 +00:00
|
|
|
$tags = $set ? $parameters : [];
|
|
|
|
'@phan-var string[] $parameters';
|
2009-01-28 19:08:18 +00:00
|
|
|
$output = '';
|
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
$checkbox =
|
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\CheckboxInputWidget( [
|
|
|
|
'name' => 'wpFilterActionTag',
|
|
|
|
'id' => 'mw-abusefilter-action-checkbox-tag',
|
|
|
|
'selected' => $set,
|
2019-02-27 10:52:59 +00:00
|
|
|
'classes' => [ 'mw-abusefilter-action-checkbox' ],
|
|
|
|
'disabled' => $readOnly
|
|
|
|
]
|
2018-03-23 09:13:41 +00:00
|
|
|
),
|
|
|
|
[
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-action-tag' )->text(),
|
|
|
|
'align' => 'inline'
|
|
|
|
]
|
|
|
|
);
|
|
|
|
$output .= $checkbox;
|
|
|
|
|
|
|
|
$tagConfig = [
|
2018-09-09 10:14:31 +00:00
|
|
|
'values' => $tags,
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-tag-tag' )->parse(),
|
2019-02-27 10:52:59 +00:00
|
|
|
'disabled' => $readOnly
|
2018-03-23 09:13:41 +00:00
|
|
|
];
|
|
|
|
$this->getOutput()->addJsConfigVars( 'tagConfig', $tagConfig );
|
|
|
|
|
|
|
|
$hiddenTags =
|
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\MultilineTextInputWidget( [
|
|
|
|
'name' => 'wpFilterTags',
|
|
|
|
'value' => implode( ',', $tags ),
|
2018-08-22 09:02:51 +00:00
|
|
|
'rows' => 5,
|
2018-08-19 16:59:26 +00:00
|
|
|
'placeholder' => $this->msg( 'abusefilter-edit-tag-hidden-placeholder' )->text(),
|
|
|
|
'infusable' => true,
|
2019-02-27 10:52:59 +00:00
|
|
|
'id' => 'mw-abusefilter-hidden-tag-field',
|
|
|
|
'readOnly' => $readOnly
|
|
|
|
]
|
2018-03-23 09:13:41 +00:00
|
|
|
),
|
|
|
|
[
|
|
|
|
'label' => new OOUI\HtmlSnippet(
|
|
|
|
$this->msg( 'abusefilter-edit-tag-tag' )->parse()
|
|
|
|
),
|
|
|
|
'align' => 'top',
|
2018-09-09 10:14:31 +00:00
|
|
|
'id' => 'mw-abusefilter-hidden-tag'
|
2018-03-23 09:13:41 +00:00
|
|
|
]
|
|
|
|
);
|
2009-10-07 13:57:06 +00:00
|
|
|
$output .=
|
2024-03-29 12:40:23 +00:00
|
|
|
Html::rawElement( 'div',
|
2017-06-15 14:23:16 +00:00
|
|
|
[ 'id' => 'mw-abusefilter-tag-parameters' ],
|
2018-03-23 09:13:41 +00:00
|
|
|
$hiddenTags
|
2009-02-07 09:34:11 +00:00
|
|
|
);
|
2009-01-28 19:08:18 +00:00
|
|
|
return $output;
|
2017-08-22 18:23:01 +00:00
|
|
|
case 'block':
|
2018-02-20 12:36:32 +00:00
|
|
|
if ( $set && count( $parameters ) === 3 ) {
|
|
|
|
// Both blocktalk and custom block durations available
|
2024-03-16 18:52:48 +00:00
|
|
|
[ $blockTalk, $defaultAnonDuration, $defaultUserDuration ] = $parameters;
|
2018-02-20 12:36:32 +00:00
|
|
|
} else {
|
|
|
|
if ( $set && count( $parameters ) === 1 ) {
|
|
|
|
// Only blocktalk available
|
|
|
|
$blockTalk = $parameters[0];
|
|
|
|
}
|
2022-11-04 13:33:43 +00:00
|
|
|
$defaultAnonDuration = $config->get( 'AbuseFilterAnonBlockDuration' ) ??
|
|
|
|
$config->get( 'AbuseFilterBlockDuration' );
|
2018-03-10 21:47:33 +00:00
|
|
|
$defaultUserDuration = $config->get( 'AbuseFilterBlockDuration' );
|
2018-02-20 12:36:32 +00:00
|
|
|
}
|
2024-05-04 08:14:01 +00:00
|
|
|
$suggestedBlocks = $this->getLanguage()->getBlockDurations( false );
|
2018-03-24 09:45:54 +00:00
|
|
|
$suggestedBlocks = self::normalizeBlocks( $suggestedBlocks );
|
2018-02-20 12:36:32 +00:00
|
|
|
|
2017-08-22 18:23:01 +00:00
|
|
|
$output = '';
|
2018-03-23 09:13:41 +00:00
|
|
|
$checkbox =
|
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\CheckboxInputWidget( [
|
|
|
|
'name' => 'wpFilterActionBlock',
|
|
|
|
'id' => 'mw-abusefilter-action-checkbox-block',
|
|
|
|
'selected' => $set,
|
2019-02-27 10:52:59 +00:00
|
|
|
'classes' => [ 'mw-abusefilter-action-checkbox' ],
|
|
|
|
'disabled' => $readOnly
|
|
|
|
]
|
2018-03-23 09:13:41 +00:00
|
|
|
),
|
|
|
|
[
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-action-block' )->text(),
|
|
|
|
'align' => 'inline'
|
|
|
|
]
|
|
|
|
);
|
|
|
|
$output .= $checkbox;
|
2018-02-20 12:36:32 +00:00
|
|
|
|
2024-05-04 08:14:01 +00:00
|
|
|
$suggestedBlocks = Html::listDropdownOptionsOoui( $suggestedBlocks );
|
2018-02-20 12:36:32 +00:00
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
$anonDuration =
|
|
|
|
new OOUI\DropdownInputWidget( [
|
|
|
|
'name' => 'wpBlockAnonDuration',
|
|
|
|
'options' => $suggestedBlocks,
|
|
|
|
'value' => $defaultAnonDuration,
|
2020-09-18 14:49:13 +00:00
|
|
|
'disabled' => $readOnly
|
2018-03-23 09:13:41 +00:00
|
|
|
] );
|
2018-02-20 12:36:32 +00:00
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
$userDuration =
|
|
|
|
new OOUI\DropdownInputWidget( [
|
|
|
|
'name' => 'wpBlockUserDuration',
|
|
|
|
'options' => $suggestedBlocks,
|
|
|
|
'value' => $defaultUserDuration,
|
2020-09-18 14:49:13 +00:00
|
|
|
'disabled' => $readOnly
|
2018-03-23 09:13:41 +00:00
|
|
|
] );
|
2018-02-20 12:36:32 +00:00
|
|
|
|
2018-08-25 16:56:44 +00:00
|
|
|
$blockOptions = [];
|
2023-06-12 08:27:03 +00:00
|
|
|
if ( $config->get( MainConfigNames::BlockAllowsUTEdit ) === true ) {
|
2018-08-25 16:56:44 +00:00
|
|
|
$talkCheckbox =
|
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\CheckboxInputWidget( [
|
|
|
|
'name' => 'wpFilterBlockTalk',
|
|
|
|
'id' => 'mw-abusefilter-action-checkbox-blocktalk',
|
2018-08-26 08:34:42 +00:00
|
|
|
'selected' => isset( $blockTalk ) && $blockTalk === 'blocktalk',
|
2019-02-27 10:52:59 +00:00
|
|
|
'classes' => [ 'mw-abusefilter-action-checkbox' ],
|
|
|
|
'disabled' => $readOnly
|
|
|
|
]
|
2018-08-25 16:56:44 +00:00
|
|
|
),
|
|
|
|
[
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-action-blocktalk' )->text(),
|
|
|
|
'align' => 'left'
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
2022-01-13 15:37:04 +00:00
|
|
|
$blockOptions[] = $talkCheckbox;
|
2018-04-28 15:21:18 +00:00
|
|
|
}
|
2022-01-13 15:37:04 +00:00
|
|
|
$blockOptions[] =
|
2018-03-23 09:13:41 +00:00
|
|
|
new OOUI\FieldLayout(
|
|
|
|
$anonDuration,
|
|
|
|
[
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-block-anon-durations' )->text()
|
|
|
|
]
|
|
|
|
);
|
2022-01-13 15:37:04 +00:00
|
|
|
$blockOptions[] =
|
2018-03-23 09:13:41 +00:00
|
|
|
new OOUI\FieldLayout(
|
|
|
|
$userDuration,
|
|
|
|
[
|
|
|
|
'label' => $this->msg( 'abusefilter-edit-block-user-durations' )->text()
|
|
|
|
]
|
|
|
|
);
|
2018-02-20 12:36:32 +00:00
|
|
|
|
2024-03-29 12:40:23 +00:00
|
|
|
$output .= Html::rawElement(
|
2018-02-20 12:36:32 +00:00
|
|
|
'div',
|
|
|
|
[ 'id' => 'mw-abusefilter-block-parameters' ],
|
2018-08-25 16:56:44 +00:00
|
|
|
new OOUI\FieldsetLayout( [ 'items' => $blockOptions ] )
|
2018-02-20 12:36:32 +00:00
|
|
|
);
|
|
|
|
|
2017-08-22 18:23:01 +00:00
|
|
|
return $output;
|
2018-02-20 12:36:32 +00:00
|
|
|
|
2009-01-23 19:23:44 +00:00
|
|
|
default:
|
2013-03-07 00:04:39 +00:00
|
|
|
// Give grep a chance to find the usages:
|
2018-03-23 09:13:41 +00:00
|
|
|
// abusefilter-edit-action-disallow,
|
|
|
|
// abusefilter-edit-action-blockautopromote,
|
|
|
|
// abusefilter-edit-action-degroup,
|
|
|
|
// abusefilter-edit-action-rangeblock,
|
2009-10-07 13:57:06 +00:00
|
|
|
$message = 'abusefilter-edit-action-' . $action;
|
|
|
|
$form_field = 'wpFilterAction' . ucfirst( $action );
|
2009-01-23 19:23:44 +00:00
|
|
|
$status = $set;
|
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
$thisAction =
|
|
|
|
new OOUI\FieldLayout(
|
|
|
|
new OOUI\CheckboxInputWidget( [
|
|
|
|
'name' => $form_field,
|
|
|
|
'id' => "mw-abusefilter-action-checkbox-$action",
|
|
|
|
'selected' => $status,
|
2019-02-27 10:52:59 +00:00
|
|
|
'classes' => [ 'mw-abusefilter-action-checkbox' ],
|
|
|
|
'disabled' => $readOnly
|
|
|
|
]
|
2018-03-23 09:13:41 +00:00
|
|
|
),
|
|
|
|
[
|
|
|
|
'label' => $this->msg( $message )->text(),
|
|
|
|
'align' => 'inline'
|
|
|
|
]
|
|
|
|
);
|
2009-01-23 19:23:44 +00:00
|
|
|
return $thisAction;
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-11 20:51:54 +00:00
|
|
|
/**
|
2017-10-06 18:52:31 +00:00
|
|
|
* @param string $warnMsg
|
|
|
|
* @param bool $readOnly
|
2014-10-04 14:42:46 +00:00
|
|
|
* @param string $action
|
2018-10-03 12:02:00 +00:00
|
|
|
* @return \OOUI\FieldLayout
|
2012-03-11 20:51:54 +00:00
|
|
|
*/
|
2014-10-04 14:42:46 +00:00
|
|
|
public function getExistingSelector( $warnMsg, $readOnly = false, $action = 'warn' ) {
|
|
|
|
if ( $action === 'warn' ) {
|
|
|
|
$action = 'warning';
|
|
|
|
$formId = 'warn';
|
|
|
|
$inputName = 'wpFilterWarnMessage';
|
|
|
|
} elseif ( $action === 'disallow' ) {
|
|
|
|
$action = 'disallowed';
|
|
|
|
$formId = 'disallow';
|
|
|
|
$inputName = 'wpFilterDisallowMessage';
|
|
|
|
} else {
|
2023-06-07 15:41:20 +00:00
|
|
|
throw new UnexpectedValueException( "Unexpected action value $action" );
|
2014-10-04 14:42:46 +00:00
|
|
|
}
|
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
$existingSelector =
|
|
|
|
new OOUI\DropdownInputWidget( [
|
2014-10-04 14:42:46 +00:00
|
|
|
'name' => $inputName,
|
|
|
|
// mw-abusefilter-warn-message-existing, mw-abusefilter-disallow-message-existing
|
|
|
|
'id' => "mw-abusefilter-$formId-message-existing",
|
|
|
|
// abusefilter-warning, abusefilter-disallowed
|
2018-08-26 08:34:42 +00:00
|
|
|
'value' => $warnMsg === "abusefilter-$action" ? "abusefilter-$action" : 'other',
|
2018-03-23 09:13:41 +00:00
|
|
|
'infusable' => true
|
|
|
|
] );
|
2009-02-03 22:45:42 +00:00
|
|
|
|
2014-10-04 14:42:46 +00:00
|
|
|
// abusefilter-warning, abusefilter-disallowed
|
|
|
|
$options = [ "abusefilter-$action" => "abusefilter-$action" ];
|
2009-02-03 22:45:42 +00:00
|
|
|
|
2016-12-15 13:09:03 +00:00
|
|
|
if ( $readOnly ) {
|
2018-03-23 09:13:41 +00:00
|
|
|
$existingSelector->setDisabled( true );
|
2016-12-15 13:09:03 +00:00
|
|
|
} else {
|
|
|
|
// Find other messages.
|
2023-02-26 12:51:08 +00:00
|
|
|
$dbr = $this->lbFactory->getReplicaDatabase();
|
2014-10-04 14:42:46 +00:00
|
|
|
$pageTitlePrefix = "Abusefilter-$action";
|
2024-04-30 18:21:20 +00:00
|
|
|
$titles = $dbr->newSelectQueryBuilder()
|
|
|
|
->select( 'page_title' )
|
|
|
|
->from( 'page' )
|
|
|
|
->where( [
|
2016-12-15 13:09:03 +00:00
|
|
|
'page_namespace' => 8,
|
2024-04-30 18:21:20 +00:00
|
|
|
$dbr->expr( 'page_title', IExpression::LIKE, new LikeValue( $pageTitlePrefix, $dbr->anyString() ) )
|
|
|
|
] )
|
|
|
|
->caller( __METHOD__ )
|
|
|
|
->fetchFieldValues();
|
2010-02-13 14:10:36 +00:00
|
|
|
|
2016-12-15 13:09:03 +00:00
|
|
|
$lang = $this->getLanguage();
|
2019-12-07 17:20:10 +00:00
|
|
|
foreach ( $titles as $title ) {
|
|
|
|
if ( $lang->lcfirst( $title ) === $lang->lcfirst( $warnMsg ) ) {
|
2018-03-23 09:13:41 +00:00
|
|
|
$existingSelector->setValue( $lang->lcfirst( $warnMsg ) );
|
2016-12-15 13:09:03 +00:00
|
|
|
}
|
|
|
|
|
2019-12-07 17:20:10 +00:00
|
|
|
if ( $title !== "Abusefilter-$action" ) {
|
|
|
|
$options[ $lang->lcfirst( $title ) ] = $lang->lcfirst( $title );
|
2016-12-15 13:09:03 +00:00
|
|
|
}
|
2009-02-03 22:45:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-04 14:42:46 +00:00
|
|
|
// abusefilter-edit-warn-other, abusefilter-edit-disallow-other
|
2019-12-07 17:20:10 +00:00
|
|
|
$options[ $this->msg( "abusefilter-edit-$formId-other" )->text() ] = 'other';
|
2018-03-23 09:13:41 +00:00
|
|
|
|
2024-05-04 08:14:01 +00:00
|
|
|
$options = Html::listDropdownOptionsOoui( $options );
|
2018-03-23 09:13:41 +00:00
|
|
|
$existingSelector->setOptions( $options );
|
|
|
|
|
|
|
|
$existingSelector =
|
|
|
|
new OOUI\FieldLayout(
|
|
|
|
$existingSelector,
|
|
|
|
[
|
2014-10-04 14:42:46 +00:00
|
|
|
// abusefilter-edit-warn-message, abusefilter-edit-disallow-message
|
|
|
|
'label' => $this->msg( "abusefilter-edit-$formId-message" )->text()
|
2018-03-23 09:13:41 +00:00
|
|
|
]
|
|
|
|
);
|
2009-02-03 22:45:42 +00:00
|
|
|
|
2018-03-23 09:13:41 +00:00
|
|
|
return $existingSelector;
|
2009-02-03 22:45:42 +00:00
|
|
|
}
|
|
|
|
|
2018-03-24 09:45:54 +00:00
|
|
|
/**
|
2018-07-27 00:27:11 +00:00
|
|
|
* @todo Maybe we should also check if global values belong to $durations
|
2018-03-24 09:45:54 +00:00
|
|
|
* and determine the right point to add them if missing.
|
|
|
|
*
|
2020-12-03 08:49:56 +00:00
|
|
|
* @param string[] $durations
|
|
|
|
* @return string[]
|
2018-03-24 09:45:54 +00:00
|
|
|
*/
|
2020-12-03 15:47:19 +00:00
|
|
|
private static function normalizeBlocks( array $durations ) {
|
2018-03-24 09:45:54 +00:00
|
|
|
global $wgAbuseFilterBlockDuration, $wgAbuseFilterAnonBlockDuration;
|
|
|
|
// We need to have same values since it may happen that ipblocklist
|
|
|
|
// and one (or both) of the global variables use different wording
|
|
|
|
// for the same duration. In such case, when setting the default of
|
|
|
|
// the dropdowns it would fail.
|
2022-11-04 13:33:43 +00:00
|
|
|
$anonDuration = self::getAbsoluteBlockDuration( $wgAbuseFilterAnonBlockDuration ??
|
|
|
|
$wgAbuseFilterBlockDuration );
|
2018-05-02 12:13:00 +00:00
|
|
|
$userDuration = self::getAbsoluteBlockDuration( $wgAbuseFilterBlockDuration );
|
2018-03-24 09:45:54 +00:00
|
|
|
foreach ( $durations as &$duration ) {
|
2018-05-02 12:13:00 +00:00
|
|
|
$currentDuration = self::getAbsoluteBlockDuration( $duration );
|
2018-03-24 09:45:54 +00:00
|
|
|
|
|
|
|
if ( $duration !== $wgAbuseFilterBlockDuration &&
|
|
|
|
$currentDuration === $userDuration ) {
|
|
|
|
$duration = $wgAbuseFilterBlockDuration;
|
|
|
|
|
|
|
|
} elseif ( $duration !== $wgAbuseFilterAnonBlockDuration &&
|
|
|
|
$currentDuration === $anonDuration ) {
|
|
|
|
$duration = $wgAbuseFilterAnonBlockDuration;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $durations;
|
|
|
|
}
|
|
|
|
|
2018-05-02 12:13:00 +00:00
|
|
|
/**
|
|
|
|
* Converts a string duration to an absolute timestamp, i.e. unrelated to the current
|
|
|
|
* time, taking into account infinity durations as well. The second parameter of
|
|
|
|
* strtotime is set to 0 in order to convert the duration in seconds (instead of
|
|
|
|
* a timestamp), thus making it unaffected by the execution time of the code.
|
|
|
|
*
|
|
|
|
* @param string $duration
|
|
|
|
* @return string|int
|
|
|
|
*/
|
2023-06-23 10:28:06 +00:00
|
|
|
private static function getAbsoluteBlockDuration( $duration ) {
|
2018-05-02 12:13:00 +00:00
|
|
|
if ( wfIsInfinity( $duration ) ) {
|
|
|
|
return 'infinity';
|
|
|
|
}
|
|
|
|
return strtotime( $duration, 0 );
|
|
|
|
}
|
|
|
|
|
2012-03-11 20:51:54 +00:00
|
|
|
/**
|
2012-05-06 05:59:35 +00:00
|
|
|
* Loads filter data from the database by ID.
|
2020-09-20 10:18:46 +00:00
|
|
|
* @param int|null $id The filter's ID number, or null for a new filter
|
2020-09-20 11:30:59 +00:00
|
|
|
* @return Filter
|
|
|
|
* @throws FilterNotFoundException
|
2012-03-11 20:51:54 +00:00
|
|
|
*/
|
2021-07-21 18:51:12 +00:00
|
|
|
private function loadFilterData( ?int $id ): Filter {
|
2020-09-20 10:18:46 +00:00
|
|
|
if ( $id === null ) {
|
2020-09-20 11:30:59 +00:00
|
|
|
return MutableFilter::newDefault();
|
2010-08-19 21:12:09 +00:00
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2020-09-20 11:30:59 +00:00
|
|
|
$flags = $this->getRequest()->wasPosted()
|
2021-05-12 23:43:37 +00:00
|
|
|
// Load from primary database to avoid unintended reversions where there's replication lag.
|
2024-01-26 13:56:58 +00:00
|
|
|
? IDBAccessObject::READ_LATEST
|
|
|
|
: IDBAccessObject::READ_NORMAL;
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2020-10-23 14:19:02 +00:00
|
|
|
return $this->filterLookup->getFilter( $id, false, $flags );
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
|
2012-03-11 20:51:54 +00:00
|
|
|
/**
|
2019-03-01 14:24:30 +00:00
|
|
|
* Load filter data to show in the edit view from the DB.
|
2020-09-20 10:18:46 +00:00
|
|
|
* @param int|null $filter The filter ID being requested or null for a new filter
|
2018-05-25 23:31:49 +00:00
|
|
|
* @param int|null $history_id If any, the history ID being requested.
|
2020-09-20 11:30:59 +00:00
|
|
|
* @return Filter|null Null if the filter does not exist.
|
2012-03-11 20:51:54 +00:00
|
|
|
*/
|
2021-07-21 18:51:12 +00:00
|
|
|
private function loadFromDatabase( ?int $filter, $history_id = null ): ?Filter {
|
2019-03-01 14:24:30 +00:00
|
|
|
if ( $history_id ) {
|
2020-09-20 11:30:59 +00:00
|
|
|
try {
|
2020-10-23 14:19:02 +00:00
|
|
|
return $this->filterLookup->getFilterVersion( $history_id );
|
2020-09-20 11:30:59 +00:00
|
|
|
} catch ( FilterVersionNotFoundException $_ ) {
|
|
|
|
return null;
|
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
} else {
|
|
|
|
return $this->loadFilterData( $filter );
|
|
|
|
}
|
2019-03-01 14:24:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-09-22 22:19:50 +00:00
|
|
|
* Load data from the HTTP request. Used for saving the filter, and when the token doesn't match
|
|
|
|
* @param int|null $filter
|
2020-09-20 11:30:59 +00:00
|
|
|
* @return Filter[]
|
2019-03-01 14:24:30 +00:00
|
|
|
*/
|
2021-07-21 18:51:12 +00:00
|
|
|
private function loadRequest( ?int $filter ): array {
|
2019-03-01 14:24:30 +00:00
|
|
|
$request = $this->getRequest();
|
|
|
|
if ( !$request->wasPosted() ) {
|
|
|
|
// Sanity
|
2023-11-16 18:52:51 +00:00
|
|
|
throw new LogicException( __METHOD__ . ' called without the request being POSTed.' );
|
2019-03-01 14:24:30 +00:00
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
|
2020-09-20 11:30:59 +00:00
|
|
|
$origFilter = $this->loadFilterData( $filter );
|
2009-01-26 22:30:42 +00:00
|
|
|
|
2023-09-04 10:52:35 +00:00
|
|
|
/** @var MutableFilter $newFilter */
|
2020-09-20 14:50:37 +00:00
|
|
|
$newFilter = $origFilter instanceof MutableFilter
|
|
|
|
? clone $origFilter
|
|
|
|
: MutableFilter::newFromParentFilter( $origFilter );
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-09-22 22:19:50 +00:00
|
|
|
if ( $filter !== null ) {
|
Simplify ViewEdit, last round
This deals with data inconsistencies in buildFilterEditor. Every
property of $row was tested in all 5 scenarios (also using Selenium) to
check when it's set. The result is in the normalizeRow method, which
aims to remove any inconsistencies, so that buildFilterEditor always
receives a "complete" row with all defaults set.
The code in buildFilterEditor is now cleaner (because there are no
isset() checks), and it gives us a unique place where we can set
defaults (rather than partly doing that in
loadRequest/loadFilterData/loadImport, and partly relying on isset).
This will be especially useful when introducing value objects to
represent filters, because now you just have to look at normalizeRow()
to tell which properties are allowed to be missing, and thus what "kind"
of filter object you need (see
I5f33227887c035e301313bbe24d1c1fefb75bc6a).
Additionally, reduce the properties that get passed around during
export/import, and make the selenium test try a roundtrip, rather than
relying on hardcoded data that may get outdated. A future patch will
refactor the import/export code.
Change-Id: Id52c466baaf6da18e2981f27a81ffdad3a509e78
2020-09-27 15:15:46 +00:00
|
|
|
// Unchangeable values
|
2020-09-20 14:50:37 +00:00
|
|
|
// @phan-suppress-next-line PhanTypeMismatchArgumentNullable
|
|
|
|
$newFilter->setThrottled( $origFilter->isThrottled() );
|
|
|
|
// @phan-suppress-next-line PhanTypeMismatchArgumentNullable
|
|
|
|
$newFilter->setHitCount( $origFilter->getHitCount() );
|
Simplify ViewEdit, last round
This deals with data inconsistencies in buildFilterEditor. Every
property of $row was tested in all 5 scenarios (also using Selenium) to
check when it's set. The result is in the normalizeRow method, which
aims to remove any inconsistencies, so that buildFilterEditor always
receives a "complete" row with all defaults set.
The code in buildFilterEditor is now cleaner (because there are no
isset() checks), and it gives us a unique place where we can set
defaults (rather than partly doing that in
loadRequest/loadFilterData/loadImport, and partly relying on isset).
This will be especially useful when introducing value objects to
represent filters, because now you just have to look at normalizeRow()
to tell which properties are allowed to be missing, and thus what "kind"
of filter object you need (see
I5f33227887c035e301313bbe24d1c1fefb75bc6a).
Additionally, reduce the properties that get passed around during
export/import, and make the selenium test try a roundtrip, rather than
relying on hardcoded data that may get outdated. A future patch will
refactor the import/export code.
Change-Id: Id52c466baaf6da18e2981f27a81ffdad3a509e78
2020-09-27 15:15:46 +00:00
|
|
|
// These are needed if the save fails and the filter is not new
|
2020-09-20 14:50:37 +00:00
|
|
|
$newFilter->setID( $origFilter->getID() );
|
|
|
|
$newFilter->setUserID( $origFilter->getUserID() );
|
|
|
|
$newFilter->setUserName( $origFilter->getUserName() );
|
|
|
|
$newFilter->setTimestamp( $origFilter->getTimestamp() );
|
2020-09-22 22:19:50 +00:00
|
|
|
}
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-09-20 14:50:37 +00:00
|
|
|
$newFilter->setName( trim( $request->getVal( 'wpFilterDescription' ) ) );
|
|
|
|
$newFilter->setRules( trim( $request->getVal( 'wpFilterRules' ) ) );
|
|
|
|
$newFilter->setComments( trim( $request->getVal( 'wpFilterNotes' ) ) );
|
2019-08-11 12:29:37 +00:00
|
|
|
|
2020-09-20 14:50:37 +00:00
|
|
|
$newFilter->setGroup( $request->getVal( 'wpFilterGroup', 'default' ) );
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-09-20 14:50:37 +00:00
|
|
|
$newFilter->setDeleted( $request->getCheck( 'wpFilterDeleted' ) );
|
|
|
|
$newFilter->setEnabled( $request->getCheck( 'wpFilterEnabled' ) );
|
|
|
|
$newFilter->setHidden( $request->getCheck( 'wpFilterHidden' ) );
|
2024-06-04 13:47:16 +00:00
|
|
|
$newFilter->setProtected( $request->getCheck( 'wpFilterProtected' ) );
|
2020-09-20 14:50:37 +00:00
|
|
|
$newFilter->setGlobal( $request->getCheck( 'wpFilterGlobal' )
|
|
|
|
&& $this->getConfig()->get( 'AbuseFilterIsCentral' ) );
|
2019-03-01 15:05:26 +00:00
|
|
|
|
2020-09-22 22:19:50 +00:00
|
|
|
$actions = $this->loadActions();
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-09-20 11:30:59 +00:00
|
|
|
$newFilter->setActions( $actions );
|
2020-02-08 20:07:44 +00:00
|
|
|
|
2020-09-20 11:30:59 +00:00
|
|
|
return [ $newFilter, $origFilter ];
|
2020-09-22 22:19:50 +00:00
|
|
|
}
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-09-22 22:19:50 +00:00
|
|
|
/**
|
2020-09-20 11:30:59 +00:00
|
|
|
* @return Filter|null
|
2020-09-22 22:19:50 +00:00
|
|
|
*/
|
2021-07-21 18:51:12 +00:00
|
|
|
private function loadImportRequest(): ?Filter {
|
2020-09-22 22:19:50 +00:00
|
|
|
$request = $this->getRequest();
|
|
|
|
if ( !$request->wasPosted() ) {
|
|
|
|
// Sanity
|
2023-11-16 18:52:51 +00:00
|
|
|
throw new LogicException( __METHOD__ . ' called without the request being POSTed.' );
|
2020-09-22 22:19:50 +00:00
|
|
|
}
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-10-15 22:00:32 +00:00
|
|
|
try {
|
2020-10-23 14:19:02 +00:00
|
|
|
$filter = $this->filterImporter->decodeData( $request->getVal( 'wpImportText' ) );
|
2020-10-15 22:00:32 +00:00
|
|
|
} catch ( InvalidImportDataException $_ ) {
|
2020-09-22 22:19:50 +00:00
|
|
|
return null;
|
|
|
|
}
|
2009-10-07 13:57:06 +00:00
|
|
|
|
2020-10-15 22:00:32 +00:00
|
|
|
return $filter;
|
2020-09-22 22:19:50 +00:00
|
|
|
}
|
2014-10-04 14:42:46 +00:00
|
|
|
|
2020-09-22 22:19:50 +00:00
|
|
|
/**
|
|
|
|
* @return array[]
|
|
|
|
*/
|
2021-07-21 18:51:12 +00:00
|
|
|
private function loadActions(): array {
|
2020-09-22 22:19:50 +00:00
|
|
|
$request = $this->getRequest();
|
2020-11-29 23:10:14 +00:00
|
|
|
$allActions = $this->consequencesRegistry->getAllEnabledActionNames();
|
2020-09-22 22:19:50 +00:00
|
|
|
$actions = [];
|
2020-11-29 23:10:14 +00:00
|
|
|
foreach ( $allActions as $action ) {
|
2020-09-22 22:19:50 +00:00
|
|
|
// Check if it's set
|
|
|
|
$enabled = $request->getCheck( 'wpFilterAction' . ucfirst( $action ) );
|
|
|
|
|
|
|
|
if ( $enabled ) {
|
|
|
|
$parameters = [];
|
|
|
|
|
|
|
|
if ( $action === 'throttle' ) {
|
|
|
|
// We need to load the parameters
|
|
|
|
$throttleCount = $request->getIntOrNull( 'wpFilterThrottleCount' );
|
|
|
|
$throttlePeriod = $request->getIntOrNull( 'wpFilterThrottlePeriod' );
|
|
|
|
// First explode with \n, which is the delimiter used in the textarea
|
|
|
|
$rawGroups = explode( "\n", $request->getText( 'wpFilterThrottleGroups' ) );
|
|
|
|
// Trim any space, both as an actual group and inside subgroups
|
|
|
|
$throttleGroups = [];
|
|
|
|
foreach ( $rawGroups as $group ) {
|
|
|
|
if ( strpos( $group, ',' ) !== false ) {
|
|
|
|
$subGroups = explode( ',', $group );
|
|
|
|
$throttleGroups[] = implode( ',', array_map( 'trim', $subGroups ) );
|
|
|
|
} elseif ( trim( $group ) !== '' ) {
|
|
|
|
$throttleGroups[] = trim( $group );
|
2018-09-03 12:03:33 +00:00
|
|
|
}
|
2009-04-23 04:23:56 +00:00
|
|
|
}
|
2010-02-13 14:10:36 +00:00
|
|
|
|
2020-09-22 22:19:50 +00:00
|
|
|
$parameters[0] = $this->filter;
|
|
|
|
$parameters[1] = "$throttleCount,$throttlePeriod";
|
|
|
|
$parameters = array_merge( $parameters, $throttleGroups );
|
|
|
|
} elseif ( $action === 'warn' ) {
|
|
|
|
$specMsg = $request->getVal( 'wpFilterWarnMessage' );
|
|
|
|
|
|
|
|
if ( $specMsg === 'other' ) {
|
|
|
|
$specMsg = $request->getVal( 'wpFilterWarnMessageOther' );
|
|
|
|
}
|
|
|
|
|
|
|
|
$parameters[0] = $specMsg;
|
|
|
|
} elseif ( $action === 'block' ) {
|
2022-03-05 17:00:09 +00:00
|
|
|
// TODO: Should save a boolean
|
2020-09-22 22:19:50 +00:00
|
|
|
$parameters[0] = $request->getCheck( 'wpFilterBlockTalk' ) ?
|
|
|
|
'blocktalk' : 'noTalkBlockSet';
|
|
|
|
$parameters[1] = $request->getVal( 'wpBlockAnonDuration' );
|
|
|
|
$parameters[2] = $request->getVal( 'wpBlockUserDuration' );
|
|
|
|
} elseif ( $action === 'disallow' ) {
|
|
|
|
$specMsg = $request->getVal( 'wpFilterDisallowMessage' );
|
|
|
|
|
|
|
|
if ( $specMsg === 'other' ) {
|
|
|
|
$specMsg = $request->getVal( 'wpFilterDisallowMessageOther' );
|
|
|
|
}
|
|
|
|
|
|
|
|
$parameters[0] = $specMsg;
|
|
|
|
} elseif ( $action === 'tag' ) {
|
|
|
|
$parameters = explode( ',', trim( $request->getText( 'wpFilterTags' ) ) );
|
|
|
|
if ( $parameters === [ '' ] ) {
|
|
|
|
// Since it's not possible to manually add an empty tag, this only happens
|
|
|
|
// if the form is submitted without touching the tag input field.
|
|
|
|
// We pass an empty array so that the widget won't show an empty tag in the topbar
|
|
|
|
$parameters = [];
|
|
|
|
}
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
2020-09-22 22:19:50 +00:00
|
|
|
|
|
|
|
$actions[$action] = $parameters;
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
}
|
2020-09-22 22:19:50 +00:00
|
|
|
return $actions;
|
2009-01-23 19:23:19 +00:00
|
|
|
}
|
|
|
|
|
2017-10-20 17:46:31 +00:00
|
|
|
/**
|
2014-10-04 14:42:46 +00:00
|
|
|
* Exports the default warning and disallow messages to a JS variable
|
2017-10-20 17:46:31 +00:00
|
|
|
*/
|
2023-06-23 10:28:06 +00:00
|
|
|
private function exposeMessages() {
|
2018-03-10 21:47:33 +00:00
|
|
|
$this->getOutput()->addJsConfigVars(
|
2015-09-28 18:03:35 +00:00
|
|
|
'wgAbuseFilterDefaultWarningMessage',
|
2018-03-10 21:47:33 +00:00
|
|
|
$this->getConfig()->get( 'AbuseFilterDefaultWarningMessage' )
|
2015-09-28 18:03:35 +00:00
|
|
|
);
|
2014-10-04 14:42:46 +00:00
|
|
|
$this->getOutput()->addJsConfigVars(
|
|
|
|
'wgAbuseFilterDefaultDisallowMessage',
|
|
|
|
$this->getConfig()->get( 'AbuseFilterDefaultDisallowMessage' )
|
|
|
|
);
|
2012-06-06 05:18:31 +00:00
|
|
|
}
|
2009-02-07 09:34:11 +00:00
|
|
|
}
|