From f24991c6ed0603fa4db1d2fddb8f71f67487ac0d Mon Sep 17 00:00:00 2001 From: Dayllan Maza Date: Wed, 19 Sep 2018 01:51:49 -0400 Subject: [PATCH] Add partial block details to block-log entries. Block information needs to be more detailed if a block is not sitewide. With this change, page restrictions will be visible as part of the block information in Special:Contributions, Special:Block, and Special:Log and via API Bug: T197108 Change-Id: I5d2ef606f709bdd60bf52e2a048890b0f6360fca --- includes/logging/BlockLogFormatter.php | 44 +++++++++++ includes/specials/SpecialBlock.php | 14 +++- languages/i18n/en.json | 4 + languages/i18n/qqq.json | 4 + .../logging/BlockLogFormatterTest.php | 73 +++++++++++++++++++ 5 files changed, 137 insertions(+), 2 deletions(-) diff --git a/includes/logging/BlockLogFormatter.php b/includes/logging/BlockLogFormatter.php index 3762d62787..2698cbee2d 100644 --- a/includes/logging/BlockLogFormatter.php +++ b/includes/logging/BlockLogFormatter.php @@ -68,6 +68,17 @@ class BlockLogFormatter extends LogFormatter { ); $params[5] = isset( $params[5] ) ? self::formatBlockFlags( $params[5], $this->context->getLanguage() ) : ''; + + // block restrictions + if ( isset( $params[6] ) ) { + $pages = $params[6]['pages'] ?? []; + $pages = array_map( function ( $page ){ + return $this->makePageLink( Title::newFromText( ( $page ) ) ); + }, $pages ); + + $params[6] = Message::rawParam( $this->context->getLanguage()->listToText( $pages ) ); + $params[7] = count( $pages ); + } } return $params; @@ -188,6 +199,7 @@ class BlockLogFormatter extends LogFormatter { '6:array:flags', '6::flags' => '6:array:flags', ]; + foreach ( $map as $index => $key ) { if ( isset( $params[$index] ) ) { $params[$key] = $params[$index]; @@ -195,6 +207,8 @@ class BlockLogFormatter extends LogFormatter { } } + ksort( $params ); + $subtype = $entry->getSubtype(); if ( $subtype === 'block' || $subtype === 'reblock' ) { // Defaults for old log entries missing some fields @@ -226,7 +240,37 @@ class BlockLogFormatter extends LogFormatter { if ( isset( $ret['flags'] ) ) { ApiResult::setIndexedTagName( $ret['flags'], 'f' ); } + + if ( isset( $ret['restrictions']['pages'] ) ) { + $ret['restrictions']['pages'] = array_map( function ( $title ) { + return $this->formatParameterValueForApi( 'page', 'title-link', $title ); + }, $ret['restrictions']['pages'] ); + ApiResult::setIndexedTagName( $ret['restrictions']['pages'], 'p' ); + } + return $ret; } + protected function getMessageKey() { + $type = $this->entry->getType(); + $subtype = $this->entry->getSubtype(); + $sitewide = $this->entry->getParameters()['sitewide'] ?? true; + + $key = "logentry-$type-$subtype"; + if ( ( $subtype === 'block' || $subtype === 'reblock' ) && !$sitewide ) { + // $this->getMessageParameters is doing too much. We just need + // to check the presence of restrictions ($param[6]) and calling + // on parent gives us that + $params = parent::getMessageParameters(); + + // message changes depending on whether there are editing restrictions or not + if ( isset( $params[6] ) ) { + $key = "logentry-partial$type-$subtype"; + } else { + $key = "logentry-non-editing-$type-$subtype"; + } + } + + return $key; + } } diff --git a/includes/specials/SpecialBlock.php b/includes/specials/SpecialBlock.php index 4c50f6de52..6b9b9d4b83 100644 --- a/includes/specials/SpecialBlock.php +++ b/includes/specials/SpecialBlock.php @@ -910,6 +910,13 @@ class SpecialBlock extends FormSpecialPage { $logParams = []; $logParams['5::duration'] = $data['Expiry']; $logParams['6::flags'] = self::blockLogFlags( $data, $type ); + $logParams['sitewide'] = $block->isSitewide(); + + if ( $enablePartialBlocks && !empty( $data['PageRestrictions'] ) ) { + $logParams['7::restrictions'] = [ + 'pages' => explode( "\n", $data['PageRestrictions'] ), + ]; + } # Make log entry, if the name is hidden, put it in the suppression log $log_type = $data['HideUser'] ? 'suppress' : 'block'; @@ -1049,7 +1056,10 @@ class SpecialBlock extends FormSpecialPage { * @return string */ protected static function blockLogFlags( array $data, $type ) { - global $wgBlockAllowsUTEdit; + $config = RequestContext::getMain()->getConfig(); + + $blockAllowsUTEdit = $config->get( 'BlockAllowsUTEdit' ); + $flags = []; # when blocking a user the option 'anononly' is not available/has no effect @@ -1075,7 +1085,7 @@ class SpecialBlock extends FormSpecialPage { $flags[] = 'noemail'; } - if ( $wgBlockAllowsUTEdit && $data['DisableUTEdit'] ) { + if ( $blockAllowsUTEdit && $data['DisableUTEdit'] ) { // For grepping: message block-log-flags-nousertalk $flags[] = 'nousertalk'; } diff --git a/languages/i18n/en.json b/languages/i18n/en.json index ab0c439e5d..51ac79b205 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -4134,6 +4134,10 @@ "logentry-block-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} with an expiration time of $5 $6", "logentry-block-unblock": "$1 {{GENDER:$2|unblocked}} {{GENDER:$4|$3}}", "logentry-block-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} with an expiration time of $5 $6", + "logentry-partialblock-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} from editing {{PLURAL:$8||the pages}} $7 with an expiration time of $5 $6", + "logentry-partialblock-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} preventing edits on {{PLURAL:$8||the pages}} $7 with an expiration time of $5 $6", + "logentry-non-editing-block-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} from non-editing actions with an expiration time of $5 $6", + "logentry-non-editing-block-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} for non-editing actions with an expiration time of $5 $6", "logentry-suppress-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} with an expiration time of $5 $6", "logentry-suppress-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} with an expiration time of $5 $6", "logentry-import-upload": "$1 {{GENDER:$2|imported}} $3 by file upload", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index 82b7038f49..bd05c7b53b 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -4336,6 +4336,10 @@ "logentry-block-block": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n\nCf. {{msg-mw|Blocklogentry}}", "logentry-block-unblock": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n\nCf. {{msg-mw|Unblocklogentry}}", "logentry-block-reblock": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n\nCf. {{msg-mw|Reblock-logentry}}", + "logentry-partialblock-block": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n* $7 - list of pages separated by a comma\n* $8 - total number of pages\n\nCf. {{msg-mw|Blocklogentry}}", + "logentry-partialblock-reblock": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n* $7 - list of pages separated by a comma\n* $8 - total number of pages\n\nCf. {{msg-mw|Reblock-logentry}}", + "logentry-non-editing-block-block": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n\nCf. {{msg-mw|Blocklogentry}}", + "logentry-non-editing-block-reblock": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string\n\nCf. {{msg-mw|Reblock-logentry}}", "logentry-suppress-block": "{{Logentry}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string", "logentry-suppress-reblock": "{{Logentry}}\n* $4 - user name for gender or empty string for autoblocks\n* $5 - the block duration, localized and formatted with the english tooltip\n* $6 - block detail flags or empty string", "logentry-import-upload": "{{Logentry|[[Special:Log/import]]}}", diff --git a/tests/phpunit/includes/logging/BlockLogFormatterTest.php b/tests/phpunit/includes/logging/BlockLogFormatterTest.php index 03671ac870..85ccebc4eb 100644 --- a/tests/phpunit/includes/logging/BlockLogFormatterTest.php +++ b/tests/phpunit/includes/logging/BlockLogFormatterTest.php @@ -376,4 +376,77 @@ class BlockLogFormatterTest extends LogFormatterTestCase { public function testSuppressReblockLogDatabaseRows( $row, $extra ) { $this->doTestLogFormatter( $row, $extra ); } + + public function providePartialBlockLogDatabaseRows() { + return [ + [ + [ + 'type' => 'block', + 'action' => 'block', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => [ + '5::duration' => 'infinite', + '6::flags' => 'anononly', + '7::restrictions' => [ 'pages' => [ 'User:Test1', 'Main Page' ] ], + 'sitewide' => false, + ], + ], + [ + 'text' => 'Sysop blocked Logtestuser from editing the pages User:Test1 and Main Page' + . ' with an expiration time of indefinite (anonymous users only)', + 'api' => [ + 'duration' => 'infinite', + 'flags' => [ 'anononly' ], + 'restrictions' => [ 'pages' => [ + [ + 'page_ns' => 2, + 'page_title' => 'User:Test1', + ], [ + 'page_ns' => 0, + 'page_title' => 'Main Page', + ], + ], + ], + 'sitewide' => false, + ], + ], + ], + [ + [ + 'type' => 'block', + 'action' => 'block', + 'comment' => 'Block comment', + 'user' => 0, + 'user_text' => 'Sysop', + 'namespace' => NS_USER, + 'title' => 'Logtestuser', + 'params' => [ + '5::duration' => 'infinite', + '6::flags' => 'anononly', + 'sitewide' => false, + ], + ], + [ + 'text' => 'Sysop blocked Logtestuser from non-editing actions' + . ' with an expiration time of indefinite (anonymous users only)', + 'api' => [ + 'duration' => 'infinite', + 'flags' => [ 'anononly' ], + 'sitewide' => false, + ], + ], + ], + ]; + } + + /** + * @dataProvider providePartialBlockLogDatabaseRows + */ + public function testPartialBlockLogDatabaseRows( $row, $extra ) { + $this->doTestLogFormatter( $row, $extra ); + } } -- 2.20.1