This allows use of gender on Special:Log.
Old messages are kept for use in IRC.
A test was added to ensure an unchanged IRC message.
Bug: T57402
Change-Id: Ibc7fcaa5a952ff90d42a6477da4baa429f3de64b
'Blob' => __DIR__ . '/includes/db/DatabaseUtility.php',
'Block' => __DIR__ . '/includes/Block.php',
'BlockListPager' => __DIR__ . '/includes/specials/SpecialBlockList.php',
+ 'BlockLogFormatter' => __DIR__ . '/includes/logging/BlockLogFormatter.php',
'BloomCache' => __DIR__ . '/includes/cache/bloom/BloomCache.php',
'BloomCacheRedis' => __DIR__ . '/includes/cache/bloom/BloomCacheRedis.php',
'BloomFilterTitleHasLogs' => __DIR__ . '/includes/cache/bloom/BloomFilters.php',
* Extensions with custom log types may add to this array.
*/
$wgLogActions = array(
- 'block/block' => 'blocklogentry',
- 'block/unblock' => 'unblocklogentry',
- 'block/reblock' => 'reblock-logentry',
'protect/protect' => 'protectedarticle',
'protect/modify' => 'modifiedarticleprotection',
'protect/unprotect' => 'unprotectedarticle',
'protect/move_prot' => 'movedarticleprotection',
'import/upload' => 'import-logentry-upload',
'import/interwiki' => 'import-logentry-interwiki',
- 'suppress/block' => 'blocklogentry',
- 'suppress/reblock' => 'reblock-logentry',
);
/**
'managetags/delete' => 'LogFormatter',
'managetags/activate' => 'LogFormatter',
'managetags/deactivate' => 'LogFormatter',
+ 'block/block' => 'BlockLogFormatter',
+ 'block/unblock' => 'BlockLogFormatter',
+ 'block/reblock' => 'BlockLogFormatter',
+ 'suppress/block' => 'BlockLogFormatter',
+ 'suppress/reblock' => 'BlockLogFormatter',
);
/**
--- /dev/null
+<?php
+/**
+ * Formatter for block log entries.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ * @since 1.25
+ */
+
+/**
+ * This class formats block log entries.
+ *
+ * @since 1.25
+ */
+class BlockLogFormatter extends LogFormatter {
+ protected function getMessageParameters() {
+ $params = parent::getMessageParameters();
+
+ $title = $this->entry->getTarget();
+ if ( substr( $title->getText(), 0, 1 ) === '#' ) {
+ // autoblock - no user link possible
+ $params[2] = $title->getText();
+ $params[3] = ''; // no user name for gender use
+ } else {
+ // Create a user link for the blocked
+ $username = $title->getText();
+ // @todo Store the user identifier in the parameters
+ // to make this faster for future log entries
+ $targetUser = User::newFromName( $username, false );
+ $params[2] = Message::rawParam( $this->makeUserLink( $targetUser, Linker::TOOL_LINKS_NOBLOCK ) );
+ $params[3] = $username; // plain user name for gender use
+ }
+
+ $subtype = $this->entry->getSubtype();
+ if ( $subtype === 'block' || $subtype === 'reblock' ) {
+ // Localize the duration, and add a tooltip
+ // in English to help visitors from other wikis.
+ // The lrm is needed to make sure that the number
+ // is shown on the correct side of the tooltip text.
+ $durationTooltip = '‎' . htmlspecialchars( $params[4] );
+ $params[4] = Message::rawParam( "<span class='blockExpiry' title='$durationTooltip'>" .
+ $this->context->getLanguage()->translateBlockExpiry( $params[4] ) . '</span>' );
+ $params[5] = isset( $params[5] ) ?
+ self::formatBlockFlags( $params[5], $this->context->getLanguage() ) : '';
+ }
+
+ return $params;
+ }
+
+ public function getPreloadTitles() {
+ $title = $this->entry->getTarget();
+ // Preload user page for non-autoblocks
+ if ( substr( $title->getText(), 0, 1 ) !== '#' ) {
+ return array( $title->getTalkPage() );
+ }
+ return array();
+ }
+
+ public function getActionLinks() {
+ $subtype = $this->entry->getSubtype();
+ if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
+ || !( $subtype === 'block' || $subtype === 'reblock' )
+ || !$this->context->getUser()->isAllowed( 'block' )
+ ) {
+ return '';
+ }
+
+ // Show unblock/change block link
+ $title = $this->entry->getTarget();
+ $links = array(
+ Linker::linkKnown(
+ SpecialPage::getTitleFor( 'Unblock', $title->getDBkey() ),
+ $this->msg( 'unblocklink' )->escaped()
+ ),
+ Linker::linkKnown(
+ SpecialPage::getTitleFor( 'Block', $title->getDBkey() ),
+ $this->msg( 'change-blocklink' )->escaped()
+ )
+ );
+
+ return $this->msg( 'parentheses' )->rawParams(
+ $this->context->getLanguage()->pipeList( $links ) )->escaped();
+ }
+
+ /**
+ * Convert a comma-delimited list of block log flags
+ * into a more readable (and translated) form
+ *
+ * @param string $flags Flags to format
+ * @param Language $lang
+ * @return string
+ */
+ public static function formatBlockFlags( $flags, $lang ) {
+ $flags = trim( $flags );
+ if ( $flags === '' ) {
+ return ''; //nothing to do
+ }
+ $flags = explode( ',', $flags );
+ $flagsCount = count( $flags );
+
+ for ( $i = 0; $i < $flagsCount; $i++ ) {
+ $flags[$i] = self::formatBlockFlag( $flags[$i], $lang );
+ }
+
+ return wfMessage( 'parentheses' )->inLanguage( $lang )
+ ->rawParams( $lang->commaList( $flags ) )->escaped();
+ }
+
+ /**
+ * Translate a block log flag if possible
+ *
+ * @param int $flag Flag to translate
+ * @param Language $lang Language object to use
+ * @return string
+ */
+ public static function formatBlockFlag( $flag, $lang ) {
+ static $messages = array();
+
+ if ( !isset( $messages[$flag] ) ) {
+ $messages[$flag] = htmlspecialchars( $flag ); // Fallback
+
+ // For grepping. The following core messages can be used here:
+ // * block-log-flags-angry-autoblock
+ // * block-log-flags-anononly
+ // * block-log-flags-hiddenname
+ // * block-log-flags-noautoblock
+ // * block-log-flags-nocreate
+ // * block-log-flags-noemail
+ // * block-log-flags-nousertalk
+ $msg = wfMessage( 'block-log-flags-' . $flag )->inLanguage( $lang );
+
+ if ( $msg->exists() ) {
+ $messages[$flag] = $msg->escaped();
+ }
+ }
+
+ return $messages[$flag];
+ }
+}
->rawParams( $target, $parameters['4::dest'], $parameters['5::mergepoint'] )
->inContentLanguage()->escaped();
break;
+
+ case 'block':
+ switch ( $entry->getSubtype() ) {
+ case 'block':
+ global $wgContLang;
+ $duration = $wgContLang->translateBlockExpiry( $parameters['5::duration'] );
+ $flags = BlockLogFormatter::formatBlockFlags( $parameters['6::flags'], $wgContLang );
+ $text = wfMessage( 'blocklogentry' )
+ ->rawParams( $target, $duration, $flags )->inContentLanguage()->escaped();
+ break;
+ case 'unblock':
+ $text = wfMessage( 'unblocklogentry' )
+ ->rawParams( $target )->inContentLanguage()->escaped();
+ break;
+ case 'reblock':
+ global $wgContLang;
+ $duration = $wgContLang->translateBlockExpiry( $parameters['5::duration'] );
+ $flags = BlockLogFormatter::formatBlockFlags( $parameters['6::flags'], $wgContLang );
+ $text = wfMessage( 'reblock-logentry' )
+ ->rawParams( $target, $duration, $flags )->inContentLanguage()->escaped();
+ break;
+ }
+ break;
// case 'suppress' --private log -- aaron (so we know who to blame in a few years :-D)
// default:
}
return $this->context->msg( $key );
}
- protected function makeUserLink( User $user ) {
+ protected function makeUserLink( User $user, $toolFlags = 0 ) {
if ( $this->plaintext ) {
$element = $user->getName();
} else {
);
if ( $this->linkFlood ) {
- $element .= Linker::userToolLinksRedContribs(
+ $element .= Linker::userToolLinks(
$user->getId(),
$user->getName(),
+ true, // redContribsWhenNoEdits
+ $toolFlags,
$user->getEditCount()
);
}
$type = $this->entry->getType();
$subtype = $this->entry->getSubtype();
- // Show unblock/change block link
- if ( ( $type == 'block' || $type == 'suppress' )
- && ( $subtype == 'block' || $subtype == 'reblock' )
- ) {
- if ( !$this->context->getUser()->isAllowed( 'block' ) ) {
- return '';
- }
-
- $links = array(
- Linker::linkKnown(
- SpecialPage::getTitleFor( 'Unblock', $title->getDBkey() ),
- $this->msg( 'unblocklink' )->escaped()
- ),
- Linker::linkKnown(
- SpecialPage::getTitleFor( 'Block', $title->getDBkey() ),
- $this->msg( 'change-blocklink' )->escaped()
- )
- );
-
- return $this->msg( 'parentheses' )->rawParams(
- $this->context->getLanguage()->pipeList( $links ) )->escaped();
- // Show change protection link
- } elseif ( $type == 'protect'
+ if ( $type == 'protect'
&& ( $subtype == 'protect' || $subtype == 'modify' || $subtype == 'unprotect' )
) {
$links = array(
$details = '';
array_unshift( $params, $titleLink );
- // User suppression
- if ( preg_match( '/^(block|suppress)\/(block|reblock)$/', $key ) ) {
- if ( $skin ) {
- // Localize the duration, and add a tooltip
- // in English to help visitors from other wikis.
- // The lrm is needed to make sure that the number
- // is shown on the correct side of the tooltip text.
- $durationTooltip = '‎' . htmlspecialchars( $params[1] );
- $params[1] = "<span class='blockExpiry' title='$durationTooltip'>" .
- $wgLang->translateBlockExpiry( $params[1] ) . '</span>';
- } else {
- $params[1] = $wgContLang->translateBlockExpiry( $params[1] );
- }
-
- $params[2] = isset( $params[2] ) ?
- self::formatBlockFlags( $params[2], $langObj ) : '';
// Page protections
- } elseif ( $type == 'protect' && count( $params ) == 3 ) {
+ if ( $type == 'protect' && count( $params ) == 3 ) {
// Restrictions and expiries
if ( $skin ) {
$details .= $wgLang->getDirMark() . htmlspecialchars( " {$params[1]}" );
return $title->getPrefixedText();
}
- switch ( $type ) {
- case 'block':
- if ( substr( $title->getText(), 0, 1 ) == '#' ) {
- $titleLink = $title->getText();
- } else {
- // @todo Store the user identifier in the parameters
- // to make this faster for future log entries
- $id = User::idFromName( $title->getText() );
- $titleLink = Linker::userLink( $id, $title->getText() )
- . Linker::userToolLinks( $id, $title->getText(), false, Linker::TOOL_LINKS_NOBLOCK );
- }
- break;
- default:
- if ( $title->isSpecialPage() ) {
- list( $name, $par ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
-
- # Use the language name for log titles, rather than Log/X
- if ( $name == 'Log' ) {
- $logPage = new LogPage( $par );
- $titleLink = Linker::link( $title, $logPage->getName()->escaped() );
- $titleLink = wfMessage( 'parentheses' )
- ->inLanguage( $lang )
- ->rawParams( $titleLink )
- ->escaped();
- } else {
- $titleLink = Linker::link( $title );
- }
- } else {
- $titleLink = Linker::link( $title );
- }
+ if ( $title->isSpecialPage() ) {
+ list( $name, $par ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
+
+ # Use the language name for log titles, rather than Log/X
+ if ( $name == 'Log' ) {
+ $logPage = new LogPage( $par );
+ $titleLink = Linker::link( $title, $logPage->getName()->escaped() );
+ $titleLink = wfMessage( 'parentheses' )
+ ->inLanguage( $lang )
+ ->rawParams( $titleLink )
+ ->escaped();
+ } else {
+ $titleLink = Linker::link( $title );
+ }
+ } else {
+ $titleLink = Linker::link( $title );
}
return $titleLink;
}
}
- /**
- * Convert a comma-delimited list of block log flags
- * into a more readable (and translated) form
- *
- * @param string $flags Flags to format
- * @param Language $lang
- * @return string
- */
- public static function formatBlockFlags( $flags, $lang ) {
- $flags = trim( $flags );
- if ( $flags === '' ) {
- return ''; //nothing to do
- }
- $flags = explode( ',', $flags );
- $flagsCount = count( $flags );
-
- for ( $i = 0; $i < $flagsCount; $i++ ) {
- $flags[$i] = self::formatBlockFlag( $flags[$i], $lang );
- }
-
- return wfMessage( 'parentheses' )->inLanguage( $lang )
- ->rawParams( $lang->commaList( $flags ) )->escaped();
- }
-
- /**
- * Translate a block log flag if possible
- *
- * @param int $flag Flag to translate
- * @param Language $lang Language object to use
- * @return string
- */
- public static function formatBlockFlag( $flag, $lang ) {
- static $messages = array();
-
- if ( !isset( $messages[$flag] ) ) {
- $messages[$flag] = htmlspecialchars( $flag ); // Fallback
-
- // For grepping. The following core messages can be used here:
- // * block-log-flags-angry-autoblock
- // * block-log-flags-anononly
- // * block-log-flags-hiddenname
- // * block-log-flags-noautoblock
- // * block-log-flags-nocreate
- // * block-log-flags-noemail
- // * block-log-flags-nousertalk
- $msg = wfMessage( 'block-log-flags-' . $flag )->inLanguage( $lang );
-
- if ( $msg->exists() ) {
- $messages[$flag] = $msg->escaped();
- }
- }
-
- return $messages[$flag];
- }
-
/**
* Name of the log.
* @return Message
# Prepare log parameters
$logParams = array();
- $logParams[] = $data['Expiry'];
- $logParams[] = self::blockLogFlags( $data, $type );
+ $logParams['5::duration'] = $data['Expiry'];
+ $logParams['6::flags'] = self::blockLogFlags( $data, $type );
# Make log entry, if the name is hidden, put it in the oversight log
$log_type = $data['HideUser'] ? 'suppress' : 'block';
- $log = new LogPage( $log_type );
- $log_id = $log->addEntry(
- $logaction,
- Title::makeTitle( NS_USER, $target ),
- $data['Reason'][0],
- $logParams,
- $performer
- );
+ $logEntry = new ManualLogEntry( $log_type, $logaction );
+ $logEntry->setTarget( Title::makeTitle( NS_USER, $target ) );
+ $logEntry->setComment( $data['Reason'][0] );
+ $logEntry->setPerformer( $performer );
+ $logEntry->setParameters( $logParams );
# Relate log ID to block IDs (bug 25763)
$blockIds = array_merge( array( $status['id'] ), $status['autoIds'] );
- $log->addRelations( 'ipb_id', $blockIds, $log_id );
+ $logEntry->setRelations( array( 'ipb_id' => $blockIds ) );
+ $logId = $logEntry->insert();
+ $logEntry->publish( $logId );
# Report to the user
return true;
}
# Make log entry
- $log = new LogPage( 'block' );
- $log->addEntry( 'unblock', $page, $data['Reason'], array(), $performer );
+ $logEntry = new ManualLogEntry( 'block', 'unblock' );
+ $logEntry->setTarget( $page );
+ $logEntry->setComment( $data['Reason'] );
+ $logEntry->setPerformer( $performer );
+ $logId = $logEntry->insert();
+ $logEntry->publish( $logId );
return true;
}
"revdelete-uname-unhid": "username unhidden",
"revdelete-restricted": "applied restrictions to administrators",
"revdelete-unrestricted": "removed restrictions for administrators",
+ "logentry-block-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} with an expiry 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 expiry time of $5 $6",
+ "logentry-suppress-block": "$1 {{GENDER:$2|blocked}} {{GENDER:$4|$3}} with an expiry time of $5 $6",
+ "logentry-suppress-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} with an expiry time of $5 $6",
"logentry-merge-merge": "$1 {{GENDER:$2|merged}} $3 into $4 (revisions up to $5)",
"logentry-move-move": "$1 {{GENDER:$2|moved}} page $3 to $4",
"logentry-move-move-noredirect": "$1 {{GENDER:$2|moved}} page $3 to $4 without leaving a redirect",
"blocklogpage": "{{doc-logpage}}\n\nThe page name of [[Special:Log/block]]. Also appears in the drop down menu of [[Special:Log]] pages and in the action links of Special:Contributions/''Username'' pages (e.g. \"For Somebody (talk | block log | logs)\").\n\n{{Identical|Block log}}",
"blocklog-showlog": "Parameters:\n* $1 - (Optional) the blocked user. Can be used for GENDER\nSee also:\n* {{msg-mw|Blocklog-showsuppresslog}}\n* {{msg-mw|Globalblocking-showlog}}",
"blocklog-showsuppresslog": "Parameters:\n* $1 - (Optional) the blocked user. Can be used for GENDER",
- "blocklogentry": "This is the text of an entry in the Block log, and recent changes, after hour (and date, only in the Block log) and sysop name:\n* $1 - the blocked user or IP (with link to contributions and talk)\n* $2 - the duration of the block (hours, days etc.) or the specified expiry date\n* $3 - contains \"(details) (''reason'')\", or empty string\nSee also:\n* {{msg-mw|Unblocklogentry}}\n* {{msg-mw|Reblock-logentry}}",
- "reblock-logentry": "This is the text of an entry in the Block log (and Recent Changes), after hour (and date, only in the Block log) and sysop name.\n\nParameters:\n* $1 - the user being reblocked\n* $2 - the expiry time of the block\n* $3 - extra parameters like \"account creation blocked\" (they are automatically between brackets)",
+ "blocklogentry": "This is ''logentry'' message only used on IRC.\n* $1 - the blocked user or IP (with link to contributions and talk)\n* $2 - the duration of the block (hours, days etc.) or the specified expiry date\n* $3 - contains \"(details) (''reason'')\", or empty string\nSee also:\n* {{msg-mw|Unblocklogentry}}\n* {{msg-mw|Reblock-logentry}}",
+ "reblock-logentry": "This is ''logentry'' message only used on IRC.\n\nParameters:\n* $1 - the user being reblocked\n* $2 - the expiry time of the block\n* $3 - extra parameters like \"account creation blocked\" (they are automatically between brackets)",
"blocklogtext": "Appears on top of [[Special:Log/block]].",
- "unblocklogentry": "This is the text of an entry in the Block log (and Recent Changes), after hour (and date, only in the Block log) and sysop name:\n* $1 is the user being unblocked",
+ "unblocklogentry": "This is ''logentry'' message only used on IRC.\n* $1 is the user being unblocked",
"block-log-flags-anononly": "Used as a block log flag in [[Special:Log/block]] and in [[Special:Block]].\n\nSee also:\n* {{msg-mw|Anononlyblock}}\n{{Related|Block-log-flags}}",
"block-log-flags-nocreate": "Used as a block log flag in [[Special:Log/block]] and in [[Special:Block]].\n\nSee also:\n* {{msg-mw|Createaccountblock}}\n{{Related|Block-log-flags}}",
"block-log-flags-noautoblock": "Used as a block log flag in [[Special:Log/block]] and in [[Special:Block]].\n{{Related|Block-log-flags}}\n{{Identical|Autoblock disabled}}",
"revdelete-uname-unhid": "Used on\n* {{msg-mw|logentry-delete-event}}\n* {{msg-mw|logentry-delete-revision}}\n* {{msg-mw|logentry-suppress-event}}\n* {{msg-mw|logentry-suppress-event}}",
"revdelete-restricted": "Used as <code>$4</code> in the following messages when setting visibility restrictions for administrators:\n* {{msg-mw|Logentry-delete-event}}\n* {{msg-mw|Logentry-delete-revision}}\n* {{msg-mw|Logentry-suppress-event}}\n* {{msg-mw|Logentry-suppress-event}}",
"revdelete-unrestricted": "Used as <code>$4</code> in the following messages when setting visibility restrictions for administrators:\n* {{msg-mw|Logentry-delete-event}}\n* {{msg-mw|Logentry-delete-revision}}\n* {{msg-mw|Logentry-suppress-event}}\n* {{msg-mw|Logentry-suppress-event}}",
+ "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",
+ "logentry-block-unblock": "{{Logentry|[[Special:Log/block]]}}\n* $4 - user name for gender or empty string for autoblocks",
+ "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",
+ "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-merge-merge": "{{Logentry|[[Special:Log/merge]]}}\n* $4 - the page into which the content is merged\n* $5 - a timestamp of limit\n\nThe log and its associated special page 'MergeHistory' is not enabled by default.\n\nPlease note that the parameters in a log entry will appear in the log only in the default language of the wiki. View [[Special:Log]] for examples on translatewiki.net with English default language.",
"logentry-move-move": "{{Logentry|[[Special:Log/move]]}}\nParameter $4, the target page, is also not visible to parser functions.",
"logentry-move-move-noredirect": "{{Logentry|[[Special:Log/move]]}}\nParameter $4, the target page, is also not visible to parser functions.",
* Should cover the following log actions (which are most commonly used by bots):
* - block/block
* - block/unblock
+ * - block/reblock
* - delete/delete
* - delete/restore
* - newusers/create
# block/block
$this->assertIRCComment(
- $this->context->msg( 'blocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'blocklogentry', 'SomeTitle', 'duration', '(flags)' )->plain()
+ . $sep . $this->user_comment,
'block', 'block',
- array(),
+ array(
+ '5::duration' => 'duration',
+ '6::flags' => 'flags',
+ ),
$this->user_comment
);
# block/unblock
array(),
$this->user_comment
);
+ # block/reblock
+ $this->assertIRCComment(
+ $this->context->msg( 'reblock-logentry', 'SomeTitle', 'duration', '(flags)' )->plain()
+ . $sep . $this->user_comment,
+ 'block', 'reblock',
+ array(
+ '5::duration' => 'duration',
+ '6::flags' => 'flags',
+ ),
+ $this->user_comment
+ );
}
/**