Add aliases for "_text" and "article_" variables

Variables regarding title (full list in task description) are quite
deceiving, since they use "text" instead of "title". As proposed in the
task, this is the first patch to add aliases for those variables and
slightly deprecate the old ones. In the future we may be able to replace
every occurrence (either with a search function or directly on the
database), but even a coexistence would be enough to avoid
confusion. A wfDebug log is generated whenever a deprecated variable is
parsed. The "article_" prefix is also changed to "title_", in the same
way as above.
Also, added a hook which other extension may use to specify their
deprecated variables, which will be handled the same as core ones.

Bug: T173889
Change-Id: I5c370b54e6516889624088e27928ad3a1f48a821
This commit is contained in:
Daimona Eaytoy 2018-02-18 14:44:17 +01:00
parent a6c5aa8927
commit 6bc630cfef
9 changed files with 144 additions and 72 deletions

View file

@ -10,6 +10,10 @@ to add events to the AbuseFilter extension.
'AbuseFilter-builder': Allows overwriting of the builder values returned by AbuseFilter::getBuilderValues
&$realValues: Builder values
'AbuseFilter-deprecatedVariables': Allows adding deprecated variables. If a filter uses an old variable, the parser
will automatically translate it to the new one.
&$deprecatedVariables: array of deprecated variables, syntax: [ 'old_name' => 'new_name' ]
'AbuseFilter-computeVariable': Like AbuseFilter-interceptVariable but called if the requested method wasn't found.
Return true to indicate that the method is known to the hook and was computed successful.
$method: Method to generate the variable

View file

@ -310,18 +310,18 @@
"abusefilter-edit-builder-vars-new-content-model": "New content model",
"abusefilter-edit-builder-vars-removedlines": "Lines removed in edit",
"abusefilter-edit-builder-vars-summary": "Edit summary/reason",
"abusefilter-edit-builder-vars-article-id": "Page ID",
"abusefilter-edit-builder-vars-article-ns": "Page namespace",
"abusefilter-edit-builder-vars-article-text": "Page title (without namespace)",
"abusefilter-edit-builder-vars-article-prefixedtext": "Full page title",
"abusefilter-edit-builder-vars-page-id": "Page ID",
"abusefilter-edit-builder-vars-page-ns": "Page namespace",
"abusefilter-edit-builder-vars-page-title": "Page title (without namespace)",
"abusefilter-edit-builder-vars-page-prefixedtitle": "Full page title",
"abusefilter-edit-builder-vars-movedfrom-id": "Page ID of move source page",
"abusefilter-edit-builder-vars-movedfrom-ns": "Namespace of move source page",
"abusefilter-edit-builder-vars-movedfrom-text": "Title of move source page",
"abusefilter-edit-builder-vars-movedfrom-prefixedtext": "Full title of move source page",
"abusefilter-edit-builder-vars-movedfrom-title": "Title of move source page",
"abusefilter-edit-builder-vars-movedfrom-prefixedtitle": "Full title of move source page",
"abusefilter-edit-builder-vars-movedto-id": "Page ID of move destination page",
"abusefilter-edit-builder-vars-movedto-ns": "Namespace of move destination page",
"abusefilter-edit-builder-vars-movedto-text": "Title of move destination page",
"abusefilter-edit-builder-vars-movedto-prefixedtext": "Full title of move destination page",
"abusefilter-edit-builder-vars-movedto-title": "Title of move destination page",
"abusefilter-edit-builder-vars-movedto-prefixedtitle": "Full title of move destination page",
"abusefilter-edit-builder-vars-user-editcount": "Edit count of the user",
"abusefilter-edit-builder-vars-user-age": "Age of the user account",
"abusefilter-edit-builder-vars-user-name": "Name of the user account",

View file

@ -343,18 +343,18 @@
"abusefilter-edit-builder-vars-new-content-model": "New content model of the page. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-removedlines": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-summary": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-article-id": "Abuse filter syntax option in a dropdown from the group {{msg-mw|Abusefilter-edit-builder-group-vars}}.\n{{Identical|Page ID}}",
"abusefilter-edit-builder-vars-article-ns": "The namespace that the page for the trigger is supposed to be in. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-article-text": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-article-prefixedtext": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-page-id": "Abuse filter syntax option in a dropdown from the group {{msg-mw|Abusefilter-edit-builder-group-vars}}.\n{{Identical|Page ID}}",
"abusefilter-edit-builder-vars-page-ns": "The namespace that the page for the trigger is supposed to be in. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-page-title": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-page-prefixedtitle": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedfrom-id": "Paraphrase: The page ID of the page to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedfrom-ns": "Paraphrase: Namespace of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedfrom-text": "Paraphrase: Name of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedfrom-prefixedtext": "Paraphrase: Full name of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedfrom-title": "Paraphrase: Name of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedfrom-prefixedtitle": "Paraphrase: Full name of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedto-id": "Paraphrased: Page ID of the destination of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedto-ns": "Paraphrased: Namespace of the destination of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedto-text": "Paraphrased: Name of the destination of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedto-prefixedtext": "Paraphrased: Full name of the destination of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedto-title": "Paraphrased: Name of the destination of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-movedto-prefixedtitle": "Paraphrased: Full name of the destination of the page that is to be moved. Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-user-editcount": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-user-age": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"abusefilter-edit-builder-vars-user-name": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",

View file

@ -109,18 +109,18 @@ class AbuseFilter {
'old_content_model' => 'old-content-model',
'removed_lines' => 'removedlines',
'summary' => 'summary',
'article_articleid' => 'article-id',
'article_namespace' => 'article-ns',
'article_text' => 'article-text',
'article_prefixedtext' => 'article-prefixedtext',
'moved_from_articleid' => 'movedfrom-id',
'page_id' => 'page-id',
'page_namespace' => 'page-ns',
'page_title' => 'page-title',
'page_prefixedtitle' => 'page-prefixedtitle',
'moved_from_id' => 'movedfrom-id',
'moved_from_namespace' => 'movedfrom-ns',
'moved_from_text' => 'movedfrom-text',
'moved_from_prefixedtext' => 'movedfrom-prefixedtext',
'moved_to_articleid' => 'movedto-id',
'moved_from_title' => 'movedfrom-title',
'moved_from_prefixedtitle' => 'movedfrom-prefixedtitle',
'moved_to_id' => 'movedto-id',
'moved_to_namespace' => 'movedto-ns',
'moved_to_text' => 'movedto-text',
'moved_to_prefixedtext' => 'movedto-prefixedtext',
'moved_to_title' => 'movedto-title',
'moved_to_prefixedtitle' => 'movedto-prefixedtitle',
'user_editcount' => 'user-editcount',
'user_age' => 'user-age',
'user_name' => 'user-name',
@ -138,12 +138,12 @@ class AbuseFilter {
'added_lines_pst' => 'addedlines-pst',
'new_text' => 'new-text-stripped',
'new_html' => 'new-html',
'article_restrictions_edit' => 'restrictions-edit',
'article_restrictions_move' => 'restrictions-move',
'article_restrictions_create' => 'restrictions-create',
'article_restrictions_upload' => 'restrictions-upload',
'article_recent_contributors' => 'recent-contributors',
'article_first_contributor' => 'first-contributor',
'page_restrictions_edit' => 'restrictions-edit',
'page_restrictions_move' => 'restrictions-move',
'page_restrictions_create' => 'restrictions-create',
'page_restrictions_upload' => 'restrictions-upload',
'page_recent_contributors' => 'recent-contributors',
'page_first_contributor' => 'first-contributor',
'moved_from_restrictions_edit' => 'movedfrom-restrictions-edit',
'moved_from_restrictions_move' => 'movedfrom-restrictions-move',
'moved_from_restrictions_create' => 'movedfrom-restrictions-create',
@ -174,6 +174,25 @@ class AbuseFilter {
'old_html' => 'old-html'
];
public static $deprecatedVars = [
'article_text' => 'page_title',
'article_prefixedtext' => 'page_prefixedtitle',
'article_namespace' => 'page_namespace',
'article_articleid' => 'page_id',
'article_restrictions_edit' => 'page_restrictions_edit',
'article_restrictions_move' => 'page_restrictions_move',
'article_restrictions_create' => 'page_restrictions_create',
'article_restrictions_upload' => 'page_restrictions_upload',
'article_recent_contributors' => 'page_recent_contributors',
'article_first_contributor' => 'page_first_contributor',
'moved_from_text' => 'moved_from_title',
'moved_from_prefixedtext' => 'moved_from_prefixedtitle',
'moved_from_articleid' => 'moved_from_id',
'moved_to_text' => 'moved_to_title',
'moved_to_prefixedtext' => 'moved_to_prefixedtitle',
'moved_to_articleid' => 'moved_to_id',
];
public static $editboxName = null;
/**
@ -311,6 +330,23 @@ class AbuseFilter {
return $realValues;
}
/**
* @return array
*/
public static function getDeprecatedVariables() {
static $deprecatedVars = null;
if ( $deprecatedVars ) {
return $deprecatedVars;
}
$deprecatedVars = self::$deprecatedVars;
Hooks::run( 'AbuseFilter-deprecatedVariables', [ &$deprecatedVars ] );
return $deprecatedVars;
}
/**
* @param string $filter
* @return bool
@ -364,19 +400,36 @@ class AbuseFilter {
/**
* @param Title|null $title
* @param string $prefix
* @param bool $transition Temporary parameter to help with T173889 and to be removed afterwards
* @return AbuseFilterVariableHolder
*/
public static function generateTitleVars( $title, $prefix ) {
public static function generateTitleVars( $title, $prefix, $transition = true ) {
$vars = new AbuseFilterVariableHolder;
if ( !$title ) {
return $vars;
}
$vars->setVar( $prefix . '_ARTICLEID', $title->getArticleID() );
// Temporary overrides for T173889, necessary because Flow (and maybe
// other extensions) still pass old prefix/suffix and thus fail, since
// hybrid variables are generated (e.g. article_prefixedtitle).
// Once their variables will be renamed according to the new syntax,
// we should get rid of these if and just use the new prefix/suffix.
// Right now, what we want to do is:
// - Use new prefix/suffix for AF's own variables (they're handled at parser level)
// - Use old prefix/suffix for external variables (we don't handle them)
$titleSuffix = 'TITLE';
if ( $transition && $prefix === 'BOARD' ) {
$titleSuffix = 'TEXT';
}
if ( $transition && $prefix === 'ARTICLE' ) {
$prefix = 'PAGE';
}
$vars->setVar( $prefix . '_ID', $title->getArticleID() );
$vars->setVar( $prefix . '_NAMESPACE', $title->getNamespace() );
$vars->setVar( $prefix . '_TEXT', $title->getText() );
$vars->setVar( $prefix . '_PREFIXEDTEXT', $title->getPrefixedText() );
$vars->setVar( $prefix . "_$titleSuffix", $title->getText() );
$vars->setVar( $prefix . "_PREFIXED$titleSuffix", $title->getPrefixedText() );
global $wgRestrictionTypes;
foreach ( $wgRestrictionTypes as $action ) {
@ -2040,7 +2093,9 @@ class AbuseFilter {
*/
public static function getAceConfig( $canEdit ) {
$values = self::getBuilderValues();
$builderVariables = implode( '|', array_keys( $values['vars'] ) );
$deprecatedVars = self::getDeprecatedVariables();
$builderVariables = implode( '|',
array_keys( array_merge( $values['vars'], $deprecatedVars ) ) );
$builderFunctions = implode( '|', array_keys( AbuseFilterParser::$mFunctions ) );
// AbuseFilterTokenizer::$keywords also includes constants (true, false and null),
// but Ace redefines these constants afterwards so this will not be an issue
@ -2581,7 +2636,7 @@ class AbuseFilter {
$vars->addHolders(
self::generateUserVars( $user ),
self::generateTitleVars( $title, 'ARTICLE' )
self::generateTitleVars( $title, 'PAGE' )
);
$vars->setVar( 'ACTION', 'delete' );
@ -2607,7 +2662,7 @@ class AbuseFilter {
$vars->addHolders(
self::generateUserVars( $user ),
self::generateTitleVars( $title, 'ARTICLE' )
self::generateTitleVars( $title, 'PAGE' )
);
$vars->setVar( 'ACTION', 'edit' );
@ -2765,9 +2820,13 @@ class AbuseFilter {
}
// Now, build the body of the table.
$deprecatedVars = self::getDeprecatedVariables();
foreach ( $vars as $key => $value ) {
$key = strtolower( $key );
if ( array_key_exists( $key, $deprecatedVars ) ) {
$key = $deprecatedVars[$key];
}
if ( !empty( $variableMessageMappings[$key] ) ) {
$mapping = $variableMessageMappings[$key];
$keyDisplay = $context->msg( "abusefilter-edit-builder-vars-$mapping" )->parse() .

View file

@ -145,7 +145,7 @@ class AbuseFilterHooks {
$vars = new AbuseFilterVariableHolder();
$vars->addHolders(
AbuseFilter::generateUserVars( $user ),
AbuseFilter::generateTitleVars( $title, 'ARTICLE' )
AbuseFilter::generateTitleVars( $title, 'PAGE' )
);
$vars->setVar( 'action', 'edit' );
$vars->setVar( 'summary', $summary );
@ -235,7 +235,7 @@ class AbuseFilterHooks {
/** @var AbuseFilterVariableHolder|bool $vars */
$vars = self::$successful_action_vars;
if ( $vars->getVar( 'article_prefixedtext' )->toString() !==
if ( $vars->getVar( 'page_prefixedtitle' )->toString() !==
$wikiPage->getTitle()->getPrefixedText()
) {
return;
@ -350,7 +350,7 @@ class AbuseFilterHooks {
$vars->addHolders(
AbuseFilter::generateUserVars( $user ),
AbuseFilter::generateTitleVars( $article->getTitle(), 'ARTICLE' )
AbuseFilter::generateTitleVars( $article->getTitle(), 'PAGE' )
);
$vars->setVar( 'SUMMARY', $reason );

View file

@ -144,14 +144,16 @@ class AbuseFilterVariableHolder {
$coreVariables = AbuseFilter::getBuilderValues();
$coreVariables = array_keys( $coreVariables['vars'] );
$deprecatedVariables = array_keys( AbuseFilter::getDeprecatedVariables() );
$coreVariables = array_merge( $coreVariables, $deprecatedVariables );
// Title vars can have several prefixes
$prefixes = [ 'ARTICLE', 'MOVED_FROM', 'MOVED_TO' ];
$prefixes = [ 'MOVED_FROM', 'MOVED_TO', 'PAGE' ];
$titleVars = [
'_ARTICLEID',
'_ID',
'_NAMESPACE',
'_TEXT',
'_PREFIXEDTEXT',
'_TITLE',
'_PREFIXEDTITLE',
'_recent_contributors'
];
foreach ( $wgRestrictionTypes as $action ) {

View file

@ -862,6 +862,11 @@ class AbuseFilterParser {
protected function getVarValue( $var ) {
$var = strtolower( $var );
$builderValues = AbuseFilter::getBuilderValues();
$deprecatedVars = AbuseFilter::getDeprecatedVariables();
if ( array_key_exists( $var, $deprecatedVars ) ) {
wfDebug( "AbuseFilter: deprecated variable $var used." );
$var = $deprecatedVars[$var];
}
if ( !( array_key_exists( $var, $builderValues['vars'] )
|| $this->mVars->varIsSet( $var ) )
) {
@ -886,9 +891,11 @@ class AbuseFilterParser {
*/
protected function setUserVariable( $name, $value ) {
$builderValues = AbuseFilter::getBuilderValues();
$deprecatedVars = AbuseFilter::getDeprecatedVariables();
$blacklistedValues = AbuseFilterVariableHolder::$varBlacklist;
if ( array_key_exists( $name, $builderValues['vars'] ) ||
array_key_exists( $name, AbuseFilter::$disabledVars ) ||
array_key_exists( $name, $deprecatedVars ) ||
in_array( $name, $blacklistedValues ) ) {
throw new AFPUserVisibleException( 'overridebuiltin', $this->mCur->pos, [ $name ] );
}

View file

@ -79,7 +79,7 @@ class AbuseFilterConsequencesTest extends MediaWikiTestCase {
],
2 => [
'af_id' => 2,
'af_pattern' => 'action = "move" & moved_to_text contains "test"',
'af_pattern' => 'action = "move" & moved_to_title contains "test"',
'af_enabled' => 1,
'af_comments' => 'No comment',
'af_public_comments' => 'Mock filter for move',
@ -99,7 +99,7 @@ class AbuseFilterConsequencesTest extends MediaWikiTestCase {
],
3 => [
'af_id' => 3,
'af_pattern' => 'action = "delete" & "test" in lcase(article_prefixedtext)',
'af_pattern' => 'action = "delete" & "test" in lcase(page_prefixedtitle)',
'af_enabled' => 1,
'af_comments' => '',
'af_public_comments' => 'Mock filter for delete',
@ -257,7 +257,7 @@ class AbuseFilterConsequencesTest extends MediaWikiTestCase {
],
12 => [
'af_id' => 12,
'af_pattern' => 'article_text == user_name',
'af_pattern' => 'page_title == user_name',
'af_enabled' => 1,
'af_comments' => '',
'af_public_comments' => 'Mock filter for userpage',

View file

@ -279,16 +279,16 @@ class AbuseFilterTest extends MediaWikiTestCase {
}
$success = true;
switch ( $suffix ) {
case '_articleid':
case '_id':
$result = self::$mTitle->getArticleID();
break;
case '_namespace':
$result = self::$mTitle->getNamespace();
break;
case '_text':
case '_title':
$result = self::$mTitle->getText();
break;
case '_prefixedtext':
case '_prefixedtitle':
$result = self::$mTitle->getPrefixedText();
break;
case '_restrictions_create':
@ -423,24 +423,24 @@ class AbuseFilterTest extends MediaWikiTestCase {
*/
public function provideTitleVars() {
return [
[ 'article', '_articleid' ],
[ 'article', '_namespace' ],
[ 'article', '_text' ],
[ 'article', '_prefixedtext' ],
[ 'article', '_restrictions_create' ],
[ 'article', '_restrictions_create', 'restricted' ],
[ 'article', '_restrictions_edit' ],
[ 'article', '_restrictions_edit', 'restricted' ],
[ 'article', '_restrictions_move' ],
[ 'article', '_restrictions_move', 'restricted' ],
[ 'article', '_restrictions_upload' ],
[ 'article', '_restrictions_upload', 'restricted' ],
[ 'article', '_first_contributor' ],
[ 'article', '_recent_contributors' ],
[ 'moved_from', '_articleid' ],
[ 'page', '_id' ],
[ 'page', '_namespace' ],
[ 'page', '_title' ],
[ 'page', '_prefixedtitle' ],
[ 'page', '_restrictions_create' ],
[ 'page', '_restrictions_create', 'restricted' ],
[ 'page', '_restrictions_edit' ],
[ 'page', '_restrictions_edit', 'restricted' ],
[ 'page', '_restrictions_move' ],
[ 'page', '_restrictions_move', 'restricted' ],
[ 'page', '_restrictions_upload' ],
[ 'page', '_restrictions_upload', 'restricted' ],
[ 'page', '_first_contributor' ],
[ 'page', '_recent_contributors' ],
[ 'moved_from', '_id' ],
[ 'moved_from', '_namespace' ],
[ 'moved_from', '_text' ],
[ 'moved_from', '_prefixedtext' ],
[ 'moved_from', '_title' ],
[ 'moved_from', '_prefixedtitle' ],
[ 'moved_from', '_restrictions_create' ],
[ 'moved_from', '_restrictions_create', 'restricted' ],
[ 'moved_from', '_restrictions_edit' ],
@ -451,10 +451,10 @@ class AbuseFilterTest extends MediaWikiTestCase {
[ 'moved_from', '_restrictions_upload', 'restricted' ],
[ 'moved_from', '_first_contributor' ],
[ 'moved_from', '_recent_contributors' ],
[ 'moved_to', '_articleid' ],
[ 'moved_to', '_id' ],
[ 'moved_to', '_namespace' ],
[ 'moved_to', '_text' ],
[ 'moved_to', '_prefixedtext' ],
[ 'moved_to', '_title' ],
[ 'moved_to', '_prefixedtitle' ],
[ 'moved_to', '_restrictions_create' ],
[ 'moved_to', '_restrictions_create', 'restricted' ],
[ 'moved_to', '_restrictions_edit' ],