mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter.git
synced 2024-09-24 18:58:17 +00:00
Abstract methods in ViewEdit related to filter saving
Actually, it seems like I almost got it right at the first try. I tested every validation scenario and it worked as espected, so ready for review. Bug: T193596 Change-Id: I7fd1798030d83292ce46543e25c0c431ec345a28
This commit is contained in:
parent
74f5327e3f
commit
f9687ad678
|
@ -2099,6 +2099,315 @@ class AbuseFilter {
|
|||
return $loadDiv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a filter is allowed to use a tag
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @return Status
|
||||
*/
|
||||
protected static function isAllowedTag( $tag ) {
|
||||
$tagNameStatus = ChangeTags::isTagNameValid( $tag );
|
||||
|
||||
if ( !$tagNameStatus->isGood() ) {
|
||||
return $tagNameStatus;
|
||||
}
|
||||
|
||||
$finalStatus = Status::newGood();
|
||||
|
||||
$canAddStatus =
|
||||
ChangeTags::canAddTagsAccompanyingChange(
|
||||
[ $tag ]
|
||||
);
|
||||
|
||||
if ( $canAddStatus->isGood() ) {
|
||||
return $finalStatus;
|
||||
}
|
||||
|
||||
$alreadyDefinedTags = [];
|
||||
AbuseFilterHooks::onListDefinedTags( $alreadyDefinedTags );
|
||||
|
||||
if ( in_array( $tag, $alreadyDefinedTags, true ) ) {
|
||||
return $finalStatus;
|
||||
}
|
||||
|
||||
$canCreateTagStatus = ChangeTags::canCreateTag( $tag );
|
||||
if ( $canCreateTagStatus->isGood() ) {
|
||||
return $finalStatus;
|
||||
}
|
||||
|
||||
$finalStatus->fatal( 'abusefilter-edit-bad-tags' );
|
||||
return $finalStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether user input for the filter editing form is valid and if so saves the filter
|
||||
*
|
||||
* @param AbuseFilterViewEdit $page
|
||||
* @param int|string $filter
|
||||
* @param WebRequest $request
|
||||
* @param stdClass $newRow
|
||||
* @param array $actions
|
||||
* @return Status
|
||||
*/
|
||||
public static function saveFilter( $page, $filter, $request, $newRow, $actions ) {
|
||||
global $wgAbuseFilterRestrictions, $wgUser, $wgLang;
|
||||
$validationStatus = Status::newGood();
|
||||
|
||||
// Check syntax
|
||||
$syntaxerr = self::checkSyntax( $request->getVal( 'wpFilterRules' ) );
|
||||
if ( $syntaxerr !== true ) {
|
||||
$validationStatus->error( 'abusefilter-edit-badsyntax', $syntaxerr[0] );
|
||||
return $validationStatus;
|
||||
}
|
||||
// Check for missing required fields (title and pattern)
|
||||
$missing = [];
|
||||
if ( !$request->getVal( 'wpFilterRules' ) ||
|
||||
trim( $request->getVal( 'wpFilterRules' ) ) === '' ) {
|
||||
$missing[] = wfMessage( 'abusefilter-edit-field-conditions' )->escaped();
|
||||
}
|
||||
if ( !$request->getVal( 'wpFilterDescription' ) ) {
|
||||
$missing[] = wfMessage( 'abusefilter-edit-field-description' )->escaped();
|
||||
}
|
||||
if ( count( $missing ) !== 0 ) {
|
||||
$missing = $wgLang->commaList( $missing );
|
||||
$validationStatus->error( 'abusefilter-edit-missingfields', $missing );
|
||||
return $validationStatus;
|
||||
}
|
||||
|
||||
// Don't allow setting as deleted an active filter
|
||||
if ( $request->getBool( 'wpFilterEnabled' ) == true &&
|
||||
$request->getBool( 'wpFilterDeleted' ) == true ) {
|
||||
$validationStatus->error( 'abusefilter-edit-deleting-enabled' );
|
||||
return $validationStatus;
|
||||
}
|
||||
|
||||
// If we've activated the 'tag' option, check the arguments for validity.
|
||||
if ( !empty( $actions['tag'] ) ) {
|
||||
foreach ( $actions['tag']['parameters'] as $tag ) {
|
||||
$status = self::isAllowedTag( $tag );
|
||||
|
||||
if ( !$status->isGood() ) {
|
||||
$err = $status->getErrors();
|
||||
$msg = $err[0]['message'];
|
||||
$validationStatus->error( $msg );
|
||||
return $validationStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$differences = self::compareVersions(
|
||||
[ $newRow, $actions ],
|
||||
[ $newRow->mOriginalRow, $newRow->mOriginalActions ]
|
||||
);
|
||||
|
||||
// Don't allow adding a new global rule, or updating a
|
||||
// rule that is currently global, without permissions.
|
||||
if ( !$page->canEditFilter( $newRow ) || !$page->canEditFilter( $newRow->mOriginalRow ) ) {
|
||||
$validationStatus->fatal( 'abusefilter-edit-notallowed-global' );
|
||||
return $validationStatus;
|
||||
}
|
||||
|
||||
// Don't allow custom messages on global rules
|
||||
if ( $newRow->af_global == 1 &&
|
||||
$request->getVal( 'wpFilterWarnMessage' ) !== 'abusefilter-warning'
|
||||
) {
|
||||
$validationStatus->fatal( 'abusefilter-edit-notallowed-global-custom-msg' );
|
||||
return $validationStatus;
|
||||
}
|
||||
|
||||
$origActions = $newRow->mOriginalActions;
|
||||
$wasGlobal = (bool)$newRow->mOriginalRow->af_global;
|
||||
|
||||
unset( $newRow->mOriginalRow );
|
||||
unset( $newRow->mOriginalActions );
|
||||
|
||||
// Check for non-changes
|
||||
if ( !count( $differences ) ) {
|
||||
$validationStatus->setResult( true, false );
|
||||
return $validationStatus;
|
||||
}
|
||||
|
||||
// Check for restricted actions
|
||||
if ( count( array_intersect_key(
|
||||
array_filter( $wgAbuseFilterRestrictions ),
|
||||
array_merge(
|
||||
array_filter( $actions ),
|
||||
array_filter( $origActions )
|
||||
)
|
||||
) )
|
||||
&& !$wgUser->isAllowed( 'abusefilter-modify-restricted' )
|
||||
) {
|
||||
$validationStatus->error( 'abusefilter-edit-restricted' );
|
||||
return $validationStatus;
|
||||
}
|
||||
|
||||
// Everything went fine, so let's save the filter
|
||||
list( $new_id, $history_id ) =
|
||||
self::doSaveFilter( $newRow, $differences, $filter, $actions, $wasGlobal, $page );
|
||||
$validationStatus->setResult( true, [ $new_id, $history_id ] );
|
||||
return $validationStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves new filter's info to DB
|
||||
*
|
||||
* @param stdClass $newRow
|
||||
* @param int|string $filter
|
||||
* @param array $differences
|
||||
* @param array $actions
|
||||
* @param bool $wasGlobal
|
||||
* @param AbuseFilterViewEdit $page
|
||||
* @return int[] first element is new ID, second is history ID
|
||||
*/
|
||||
private static function doSaveFilter(
|
||||
$newRow,
|
||||
$differences,
|
||||
$filter,
|
||||
$actions,
|
||||
$wasGlobal,
|
||||
$page
|
||||
) {
|
||||
global $wgUser, $wgAbuseFilterActions;
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
// Convert from object to array
|
||||
$newRow = get_object_vars( $newRow );
|
||||
|
||||
// Set last modifier.
|
||||
$newRow['af_timestamp'] = $dbw->timestamp( wfTimestampNow() );
|
||||
$newRow['af_user'] = $wgUser->getId();
|
||||
$newRow['af_user_text'] = $wgUser->getName();
|
||||
|
||||
$dbw->startAtomic( __METHOD__ );
|
||||
|
||||
// Insert MAIN row.
|
||||
if ( $filter == 'new' ) {
|
||||
$new_id = $dbw->nextSequenceValue( 'abuse_filter_af_id_seq' );
|
||||
$is_new = true;
|
||||
} else {
|
||||
$new_id = $filter;
|
||||
$is_new = false;
|
||||
}
|
||||
|
||||
// Reset throttled marker, if we're re-enabling it.
|
||||
$newRow['af_throttled'] = $newRow['af_throttled'] && !$newRow['af_enabled'];
|
||||
// ID.
|
||||
$newRow['af_id'] = $new_id;
|
||||
|
||||
// T67807
|
||||
// integer 1's & 0's might be better understood than booleans
|
||||
$newRow['af_enabled'] = (int)$newRow['af_enabled'];
|
||||
$newRow['af_hidden'] = (int)$newRow['af_hidden'];
|
||||
$newRow['af_throttled'] = (int)$newRow['af_throttled'];
|
||||
$newRow['af_deleted'] = (int)$newRow['af_deleted'];
|
||||
$newRow['af_global'] = (int)$newRow['af_global'];
|
||||
|
||||
$dbw->replace( 'abuse_filter', [ 'af_id' ], $newRow, __METHOD__ );
|
||||
|
||||
if ( $is_new ) {
|
||||
$new_id = $dbw->insertId();
|
||||
}
|
||||
|
||||
// Actions
|
||||
$actionsRows = [];
|
||||
foreach ( array_filter( $wgAbuseFilterActions ) as $action => $_ ) {
|
||||
// Check if it's set
|
||||
$enabled = isset( $actions[$action] ) && (bool)$actions[$action];
|
||||
|
||||
if ( $enabled ) {
|
||||
$parameters = $actions[$action]['parameters'];
|
||||
|
||||
$thisRow = [
|
||||
'afa_filter' => $new_id,
|
||||
'afa_consequence' => $action,
|
||||
'afa_parameters' => implode( "\n", $parameters )
|
||||
];
|
||||
$actionsRows[] = $thisRow;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a history row
|
||||
$afh_row = [];
|
||||
|
||||
foreach ( self::$history_mappings as $af_col => $afh_col ) {
|
||||
$afh_row[$afh_col] = $newRow[$af_col];
|
||||
}
|
||||
|
||||
// Actions
|
||||
$displayActions = [];
|
||||
foreach ( $actions as $action ) {
|
||||
$displayActions[$action['action']] = $action['parameters'];
|
||||
}
|
||||
$afh_row['afh_actions'] = serialize( $displayActions );
|
||||
|
||||
$afh_row['afh_changed_fields'] = implode( ',', $differences );
|
||||
|
||||
// Flags
|
||||
$flags = [];
|
||||
if ( $newRow['af_hidden'] ) {
|
||||
$flags[] = 'hidden';
|
||||
}
|
||||
if ( $newRow['af_enabled'] ) {
|
||||
$flags[] = 'enabled';
|
||||
}
|
||||
if ( $newRow['af_deleted'] ) {
|
||||
$flags[] = 'deleted';
|
||||
}
|
||||
if ( $newRow['af_global'] ) {
|
||||
$flags[] = 'global';
|
||||
}
|
||||
|
||||
$afh_row['afh_flags'] = implode( ',', $flags );
|
||||
|
||||
$afh_row['afh_filter'] = $new_id;
|
||||
$afh_row['afh_id'] = $dbw->nextSequenceValue( 'abuse_filter_af_id_seq' );
|
||||
|
||||
// Do the update
|
||||
$dbw->insert( 'abuse_filter_history', $afh_row, __METHOD__ );
|
||||
$history_id = $dbw->insertId();
|
||||
if ( $filter != 'new' ) {
|
||||
$dbw->delete(
|
||||
'abuse_filter_action',
|
||||
[ 'afa_filter' => $filter ],
|
||||
__METHOD__
|
||||
);
|
||||
}
|
||||
$dbw->insert( 'abuse_filter_action', $actionsRows, __METHOD__ );
|
||||
|
||||
$dbw->endAtomic( __METHOD__ );
|
||||
|
||||
// Invalidate cache if this was a global rule
|
||||
if ( $wasGlobal || $newRow['af_global'] ) {
|
||||
$group = 'default';
|
||||
if ( isset( $newRow['af_group'] ) && $newRow['af_group'] != '' ) {
|
||||
$group = $newRow['af_group'];
|
||||
}
|
||||
|
||||
$globalRulesKey = self::getGlobalRulesKey( $group );
|
||||
ObjectCache::getMainWANInstance()->touchCheckKey( $globalRulesKey );
|
||||
}
|
||||
|
||||
// Logging
|
||||
$subtype = $filter === 'new' ? 'create' : 'modify';
|
||||
$logEntry = new ManualLogEntry( 'abusefilter', $subtype );
|
||||
$logEntry->setPerformer( $wgUser );
|
||||
$logEntry->setTarget( $page->getTitle( $new_id ) );
|
||||
$logEntry->setParameters( [
|
||||
'historyId' => $history_id,
|
||||
'newId' => $new_id
|
||||
] );
|
||||
$logid = $logEntry->insert();
|
||||
$logEntry->publish( $logid );
|
||||
|
||||
// Purge the tag list cache so the fetchAllTags hook applies tag changes
|
||||
if ( isset( $actions['tag'] ) ) {
|
||||
AbuseFilterHooks::purgeTagCache();
|
||||
}
|
||||
|
||||
self::resetFilterProfile( $new_id );
|
||||
return [ $new_id, $history_id ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Each version is expected to be an array( $row, $actions )
|
||||
* Returns an array of fields that are different.
|
||||
|
|
|
@ -11,46 +11,6 @@ class AbuseFilterViewEdit extends AbuseFilterView {
|
|||
$this->mHistoryID = $page->mHistoryID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a filter is allowed to use a tag
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @return Status
|
||||
*/
|
||||
protected function isAllowedTag( $tag ) {
|
||||
$tagNameStatus = ChangeTags::isTagNameValid( $tag );
|
||||
|
||||
if ( !$tagNameStatus->isGood() ) {
|
||||
return $tagNameStatus;
|
||||
}
|
||||
|
||||
$finalStatus = Status::newGood();
|
||||
|
||||
$canAddStatus =
|
||||
ChangeTags::canAddTagsAccompanyingChange(
|
||||
[ $tag ]
|
||||
);
|
||||
|
||||
if ( $canAddStatus->isGood() ) {
|
||||
return $finalStatus;
|
||||
}
|
||||
|
||||
$alreadyDefinedTags = [];
|
||||
AbuseFilterHooks::onListDefinedTags( $alreadyDefinedTags );
|
||||
|
||||
if ( in_array( $tag, $alreadyDefinedTags, true ) ) {
|
||||
return $finalStatus;
|
||||
}
|
||||
|
||||
$canCreateTagStatus = ChangeTags::canCreateTag( $tag );
|
||||
if ( $canCreateTagStatus->isGood() ) {
|
||||
return $finalStatus;
|
||||
}
|
||||
|
||||
$finalStatus->fatal( 'abusefilter-edit-bad-tags' );
|
||||
return $finalStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the page
|
||||
*/
|
||||
|
@ -94,276 +54,40 @@ class AbuseFilterViewEdit extends AbuseFilterView {
|
|||
$editToken, [ 'abusefilter', $filter ], $request );
|
||||
|
||||
if ( $tokenMatches && $this->canEdit() ) {
|
||||
// Check syntax
|
||||
$syntaxerr = AbuseFilter::checkSyntax( $request->getVal( 'wpFilterRules' ) );
|
||||
if ( $syntaxerr !== true ) {
|
||||
$out->addHTML(
|
||||
$this->buildFilterEditor(
|
||||
$this->msg(
|
||||
'abusefilter-edit-badsyntax',
|
||||
[ $syntaxerr[0] ]
|
||||
)->parseAsBlock(),
|
||||
$filter, $history_id
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Check for missing required fields (title and pattern)
|
||||
$missing = [];
|
||||
if ( !$request->getVal( 'wpFilterRules' ) ||
|
||||
trim( $request->getVal( 'wpFilterRules' ) ) === '' ) {
|
||||
$missing[] = $this->msg( 'abusefilter-edit-field-conditions' )->escaped();
|
||||
}
|
||||
if ( !$request->getVal( 'wpFilterDescription' ) ) {
|
||||
$missing[] = $this->msg( 'abusefilter-edit-field-description' )->escaped();
|
||||
}
|
||||
if ( count( $missing ) !== 0 ) {
|
||||
$missing = $this->getLanguage()->commaList( $missing );
|
||||
$out->addHTML(
|
||||
$this->buildFilterEditor(
|
||||
$this->msg(
|
||||
'abusefilter-edit-missingfields',
|
||||
$missing
|
||||
)->parseAsBlock(),
|
||||
$filter, $history_id
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't allow setting as deleted an active filter
|
||||
if ( $request->getBool( 'wpFilterEnabled' ) == true &&
|
||||
$request->getBool( 'wpFilterDeleted' ) == true ) {
|
||||
$out->addHTML(
|
||||
$this->buildFilterEditor(
|
||||
$this->msg(
|
||||
'abusefilter-edit-deleting-enabled'
|
||||
)->parseAsBlock(),
|
||||
$filter, $history_id
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
list( $newRow, $actions ) = $this->loadRequest( $filter );
|
||||
|
||||
$differences = AbuseFilter::compareVersions(
|
||||
[ $newRow, $actions ],
|
||||
[ $newRow->mOriginalRow, $newRow->mOriginalActions ]
|
||||
);
|
||||
|
||||
// Don't allow adding a new global rule, or updating a
|
||||
// rule that is currently global, without permissions.
|
||||
if ( !$this->canEditFilter( $newRow ) || !$this->canEditFilter( $newRow->mOriginalRow ) ) {
|
||||
$out->addWikiMsg( 'abusefilter-edit-notallowed-global' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't allow custom messages on global rules
|
||||
if ( $newRow->af_global == 1 &&
|
||||
$request->getVal( 'wpFilterWarnMessage' ) !== 'abusefilter-warning'
|
||||
) {
|
||||
$out->addWikiMsg( 'abusefilter-edit-notallowed-global-custom-msg' );
|
||||
return;
|
||||
}
|
||||
|
||||
$origActions = $newRow->mOriginalActions;
|
||||
$wasGlobal = (bool)$newRow->mOriginalRow->af_global;
|
||||
|
||||
unset( $newRow->mOriginalRow );
|
||||
unset( $newRow->mOriginalActions );
|
||||
|
||||
// Check for non-changes
|
||||
if ( !count( $differences ) ) {
|
||||
$out->redirect( $this->getTitle()->getLocalURL() );
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for restricted actions
|
||||
if ( count( array_intersect_key(
|
||||
array_filter( $config->get( 'AbuseFilterRestrictions' ) ),
|
||||
array_merge(
|
||||
array_filter( $actions ),
|
||||
array_filter( $origActions )
|
||||
)
|
||||
) )
|
||||
&& !$user->isAllowed( 'abusefilter-modify-restricted' )
|
||||
) {
|
||||
$out->addHTML(
|
||||
$this->buildFilterEditor(
|
||||
$this->msg( 'abusefilter-edit-restricted' )->parseAsBlock(),
|
||||
$this->mFilter,
|
||||
$history_id
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we've activated the 'tag' option, check the arguments for validity.
|
||||
if ( !empty( $actions['tag'] ) ) {
|
||||
foreach ( $actions['tag']['parameters'] as $tag ) {
|
||||
$status = $this->isAllowedTag( $tag );
|
||||
|
||||
if ( !$status->isGood() ) {
|
||||
$out->addHTML(
|
||||
$this->buildFilterEditor(
|
||||
$status->getMessage()->parseAsBlock(),
|
||||
$this->mFilter,
|
||||
$history_id
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
$status = AbuseFilter::saveFilter( $this, $filter, $request, $newRow, $actions );
|
||||
if ( !$status->isGood() ) {
|
||||
$err = $status->getErrors();
|
||||
$msg = $err[0]['message'];
|
||||
$params = $err[0]['params'];
|
||||
if ( $status->isOK() ) {
|
||||
$out->addHTML(
|
||||
$this->buildFilterEditor(
|
||||
$this->msg( $msg, $params )->parseAsBlock(),
|
||||
$filter,
|
||||
$history_id
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$out->addWikiMsg( $msg );
|
||||
}
|
||||
}
|
||||
|
||||
// Convert from object to array
|
||||
$newRow = get_object_vars( $newRow );
|
||||
|
||||
// Set last modifier.
|
||||
$newRow['af_timestamp'] = $dbw->timestamp( wfTimestampNow() );
|
||||
$newRow['af_user'] = $user->getId();
|
||||
$newRow['af_user_text'] = $user->getName();
|
||||
|
||||
$dbw->startAtomic( __METHOD__ );
|
||||
|
||||
// Insert MAIN row.
|
||||
if ( $filter == 'new' ) {
|
||||
$new_id = $dbw->nextSequenceValue( 'abuse_filter_af_id_seq' );
|
||||
$is_new = true;
|
||||
} else {
|
||||
$new_id = $this->mFilter;
|
||||
$is_new = false;
|
||||
}
|
||||
|
||||
// Reset throttled marker, if we're re-enabling it.
|
||||
$newRow['af_throttled'] = $newRow['af_throttled'] && !$newRow['af_enabled'];
|
||||
// ID.
|
||||
$newRow['af_id'] = $new_id;
|
||||
|
||||
// T67807
|
||||
// integer 1's & 0's might be better understood than booleans
|
||||
$newRow['af_enabled'] = (int)$newRow['af_enabled'];
|
||||
$newRow['af_hidden'] = (int)$newRow['af_hidden'];
|
||||
$newRow['af_throttled'] = (int)$newRow['af_throttled'];
|
||||
$newRow['af_deleted'] = (int)$newRow['af_deleted'];
|
||||
$newRow['af_global'] = (int)$newRow['af_global'];
|
||||
|
||||
$dbw->replace( 'abuse_filter', [ 'af_id' ], $newRow, __METHOD__ );
|
||||
|
||||
if ( $is_new ) {
|
||||
$new_id = $dbw->insertId();
|
||||
}
|
||||
|
||||
// Actions
|
||||
$actionsRows = [];
|
||||
foreach ( array_filter( $config->get( 'AbuseFilterActions' ) ) as $action => $_ ) {
|
||||
// Check if it's set
|
||||
$enabled = isset( $actions[$action] ) && (bool)$actions[$action];
|
||||
|
||||
if ( $enabled ) {
|
||||
$parameters = $actions[$action]['parameters'];
|
||||
|
||||
$thisRow = [
|
||||
'afa_filter' => $new_id,
|
||||
'afa_consequence' => $action,
|
||||
'afa_parameters' => implode( "\n", $parameters )
|
||||
];
|
||||
$actionsRows[] = $thisRow;
|
||||
if ( $status->getValue() === false ) {
|
||||
// No change
|
||||
$out->redirect( $this->getTitle()->getLocalURL() );
|
||||
} else {
|
||||
list( $new_id, $history_id ) = $status->getValue();
|
||||
$out->redirect(
|
||||
$this->getTitle()->getLocalURL(
|
||||
[
|
||||
'result' => 'success',
|
||||
'changedfilter' => $new_id,
|
||||
'changeid' => $history_id,
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a history row
|
||||
$afh_row = [];
|
||||
|
||||
foreach ( AbuseFilter::$history_mappings as $af_col => $afh_col ) {
|
||||
$afh_row[$afh_col] = $newRow[$af_col];
|
||||
}
|
||||
|
||||
// Actions
|
||||
$displayActions = [];
|
||||
foreach ( $actions as $action ) {
|
||||
$displayActions[$action['action']] = $action['parameters'];
|
||||
}
|
||||
$afh_row['afh_actions'] = serialize( $displayActions );
|
||||
|
||||
$afh_row['afh_changed_fields'] = implode( ',', $differences );
|
||||
|
||||
// Flags
|
||||
$flags = [];
|
||||
if ( $newRow['af_hidden'] ) {
|
||||
$flags[] = 'hidden';
|
||||
}
|
||||
if ( $newRow['af_enabled'] ) {
|
||||
$flags[] = 'enabled';
|
||||
}
|
||||
if ( $newRow['af_deleted'] ) {
|
||||
$flags[] = 'deleted';
|
||||
}
|
||||
if ( $newRow['af_global'] ) {
|
||||
$flags[] = 'global';
|
||||
}
|
||||
|
||||
$afh_row['afh_flags'] = implode( ',', $flags );
|
||||
|
||||
$afh_row['afh_filter'] = $new_id;
|
||||
$afh_row['afh_id'] = $dbw->nextSequenceValue( 'abuse_filter_af_id_seq' );
|
||||
|
||||
// Do the update
|
||||
$dbw->insert( 'abuse_filter_history', $afh_row, __METHOD__ );
|
||||
$history_id = $dbw->insertId();
|
||||
if ( $filter != 'new' ) {
|
||||
$dbw->delete(
|
||||
'abuse_filter_action',
|
||||
[ 'afa_filter' => $filter ],
|
||||
__METHOD__
|
||||
);
|
||||
}
|
||||
$dbw->insert( 'abuse_filter_action', $actionsRows, __METHOD__ );
|
||||
|
||||
$dbw->endAtomic( __METHOD__ );
|
||||
|
||||
// Invalidate cache if this was a global rule
|
||||
if ( $wasGlobal || $newRow['af_global'] ) {
|
||||
$group = 'default';
|
||||
if ( isset( $newRow['af_group'] ) && $newRow['af_group'] != '' ) {
|
||||
$group = $newRow['af_group'];
|
||||
}
|
||||
|
||||
$globalRulesKey = AbuseFilter::getGlobalRulesKey( $group );
|
||||
ObjectCache::getMainWANInstance()->touchCheckKey( $globalRulesKey );
|
||||
}
|
||||
|
||||
// Logging
|
||||
$subtype = $filter === 'new' ? 'create' : 'modify';
|
||||
$logEntry = new ManualLogEntry( 'abusefilter', $subtype );
|
||||
$logEntry->setPerformer( $user );
|
||||
$logEntry->setTarget( $this->getTitle( $new_id ) );
|
||||
$logEntry->setParameters( [
|
||||
'historyId' => $history_id,
|
||||
'newId' => $new_id
|
||||
] );
|
||||
$logid = $logEntry->insert();
|
||||
$logEntry->publish( $logid );
|
||||
|
||||
// Purge the tag list cache so the fetchAllTags hook applies tag changes
|
||||
if ( isset( $actions['tag'] ) ) {
|
||||
AbuseFilterHooks::purgeTagCache();
|
||||
}
|
||||
|
||||
AbuseFilter::resetFilterProfile( $new_id );
|
||||
|
||||
$out->redirect(
|
||||
$this->getTitle()->getLocalURL(
|
||||
[
|
||||
'result' => 'success',
|
||||
'changedfilter' => $new_id,
|
||||
'changeid' => $history_id,
|
||||
]
|
||||
)
|
||||
);
|
||||
} else {
|
||||
if ( $tokenMatches ) {
|
||||
// lost rights meanwhile
|
||||
|
|
Loading…
Reference in a new issue