summaryrefslogtreecommitdiff
path: root/includes/logging
diff options
context:
space:
mode:
Diffstat (limited to 'includes/logging')
-rw-r--r--includes/logging/BlockLogFormatter.php224
-rw-r--r--includes/logging/DeleteLogFormatter.php78
-rw-r--r--includes/logging/LogEntry.php38
-rw-r--r--includes/logging/LogEventsList.php76
-rw-r--r--includes/logging/LogFormatter.php253
-rw-r--r--includes/logging/LogPage.php156
-rw-r--r--includes/logging/LogPager.php2
-rw-r--r--includes/logging/MergeLogFormatter.php91
-rw-r--r--includes/logging/MoveLogFormatter.php29
-rw-r--r--includes/logging/PatrolLogFormatter.php20
-rw-r--r--includes/logging/RightsLogFormatter.php65
-rw-r--r--includes/logging/TagLogFormatter.php49
-rw-r--r--includes/logging/UploadLogFormatter.php49
13 files changed, 876 insertions, 254 deletions
diff --git a/includes/logging/BlockLogFormatter.php b/includes/logging/BlockLogFormatter.php
new file mode 100644
index 00000000..07ef24b4
--- /dev/null
+++ b/includes/logging/BlockLogFormatter.php
@@ -0,0 +1,224 @@
+<?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' ) {
+ if ( !isset( $params[4] ) ) {
+ // Very old log entry without duration: means infinite
+ $params[4] = 'infinite';
+ }
+ // 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 = '&lrm;' . 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;
+ }
+
+ protected function extractParameters() {
+ $params = parent::extractParameters();
+ // Legacy log params returning the params in index 3 and 4, moved to 4 and 5
+ if ( $this->entry->isLegacy() && isset( $params[3] ) ) {
+ if ( isset( $params[4] ) ) {
+ $params[5] = $params[4];
+ }
+ $params[4] = $params[3];
+ $params[3] = '';
+ }
+ 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];
+ }
+
+ protected function getParametersForApi() {
+ $entry = $this->entry;
+ $params = $entry->getParameters();
+
+ static $map = array(
+ // While this looks wrong to be starting at 5 rather than 4, it's
+ // because getMessageParameters uses $4 for its own purposes.
+ '5::duration',
+ '6:array:flags',
+ '6::flags' => '6:array:flags',
+ );
+ foreach ( $map as $index => $key ) {
+ if ( isset( $params[$index] ) ) {
+ $params[$key] = $params[$index];
+ unset( $params[$index] );
+ }
+ }
+
+ $subtype = $entry->getSubtype();
+ if ( $subtype === 'block' || $subtype === 'reblock' ) {
+ // Defaults for old log entries missing some fields
+ $params += array(
+ '5::duration' => 'infinite',
+ '6:array:flags' => array(),
+ );
+
+ if ( !is_array( $params['6:array:flags'] ) ) {
+ $params['6:array:flags'] = $params['6:array:flags'] === ''
+ ? array()
+ : explode( ',', $params['6:array:flags'] );
+ }
+
+ if ( !wfIsInfinity( $params['5::duration'] ) ) {
+ $ts = wfTimestamp( TS_UNIX, $entry->getTimestamp() );
+ $expiry = strtotime( $params['5::duration'], $ts );
+ if ( $expiry !== false && $expiry > 0 ) {
+ $params[':timestamp:expiry'] = $expiry;
+ }
+ }
+ }
+
+ return $params;
+ }
+
+ public function formatParametersForApi() {
+ $ret = parent::formatParametersForApi();
+ if ( isset( $ret['flags'] ) ) {
+ ApiResult::setIndexedTagName( $ret['flags'], 'f' );
+ }
+ return $ret;
+ }
+
+}
diff --git a/includes/logging/DeleteLogFormatter.php b/includes/logging/DeleteLogFormatter.php
index 8b30e9ba..f0598aa7 100644
--- a/includes/logging/DeleteLogFormatter.php
+++ b/includes/logging/DeleteLogFormatter.php
@@ -79,8 +79,10 @@ class DeleteLogFormatter extends LogFormatter {
$newParams = array_slice( $params, 0, 3 );
$newParams[3] = $changeText;
- $count = count( explode( ',', $params[$paramStart] ) );
- $newParams[4] = $this->context->getLanguage()->formatNum( $count );
+ $ids = is_array( $params[$paramStart] )
+ ? $params[$paramStart]
+ : explode( ',', $params[$paramStart] );
+ $newParams[4] = $this->context->getLanguage()->formatNum( count( $ids ) );
$this->parsedParametersDeleteLog = $newParams;
return $this->parsedParametersDeleteLog;
@@ -137,8 +139,10 @@ class DeleteLogFormatter extends LogFormatter {
// Different revision types use different URL params...
$key = $params[3];
- // This is a CSV of the IDs
- $ids = explode( ',', $params[4] );
+ // This is a array or CSV of the IDs
+ $ids = is_array( $params[4] )
+ ? $params[4]
+ : explode( ',', $params[4] );
$links = array();
@@ -192,6 +196,9 @@ class DeleteLogFormatter extends LogFormatter {
}
// This is a CSV of the IDs
$query = $params[3];
+ if ( is_array( $query ) ) {
+ $query = implode( ',', $query );
+ }
// Link to each hidden object ID, $params[1] is the url param
$revert = Linker::linkKnown(
SpecialPage::getTitleFor( 'Revisiondelete' ),
@@ -209,4 +216,67 @@ class DeleteLogFormatter extends LogFormatter {
return '';
}
}
+
+ protected function getParametersForApi() {
+ $entry = $this->entry;
+ $params = array();
+
+ $subtype = $this->entry->getSubtype();
+ if ( in_array( $subtype, array( 'event', 'revision' ) ) ) {
+ $rawParams = $entry->getParameters();
+ if ( $subtype === 'event' ) {
+ array_unshift( $rawParams, 'logging' );
+ }
+
+ static $map = array(
+ '4::type',
+ '5::ids',
+ '6::ofield',
+ '7::nfield',
+ '4::ids' => '5::ids',
+ '5::ofield' => '6::ofield',
+ '6::nfield' => '7::nfield',
+ );
+ foreach ( $map as $index => $key ) {
+ if ( isset( $rawParams[$index] ) ) {
+ $rawParams[$key] = $rawParams[$index];
+ unset( $rawParams[$index] );
+ }
+ }
+
+ $old = $this->parseBitField( $rawParams['6::ofield'] );
+ $new = $this->parseBitField( $rawParams['7::nfield'] );
+ if ( !is_array( $rawParams['5::ids'] ) ) {
+ $rawParams['5::ids'] = explode( ',', $rawParams['5::ids'] );
+ }
+
+ $params = array(
+ '::type' => $rawParams['4::type'],
+ ':array:ids' => $rawParams['5::ids'],
+ ':assoc:old' => array( 'bitmask' => $old ),
+ ':assoc:new' => array( 'bitmask' => $new ),
+ );
+
+ static $fields = array(
+ Revision::DELETED_TEXT => 'content',
+ Revision::DELETED_COMMENT => 'comment',
+ Revision::DELETED_USER => 'user',
+ Revision::DELETED_RESTRICTED => 'restricted',
+ );
+ foreach ( $fields as $bit => $key ) {
+ $params[':assoc:old'][$key] = (bool)( $old & $bit );
+ $params[':assoc:new'][$key] = (bool)( $new & $bit );
+ }
+ }
+
+ return $params;
+ }
+
+ public function formatParametersForApi() {
+ $ret = parent::formatParametersForApi();
+ if ( isset( $ret['ids'] ) ) {
+ ApiResult::setIndexedTagName( $ret['ids'], 'id' );
+ }
+ return $ret;
+ }
}
diff --git a/includes/logging/LogEntry.php b/includes/logging/LogEntry.php
index 46c55157..66c2bde1 100644
--- a/includes/logging/LogEntry.php
+++ b/includes/logging/LogEntry.php
@@ -370,6 +370,9 @@ class ManualLogEntry extends LogEntryBase {
/** @var int ID of the log entry */
protected $id;
+ /** @var bool Whether this is a legacy log entry */
+ protected $legacy = false;
+
/**
* Constructor.
*
@@ -385,13 +388,14 @@ class ManualLogEntry extends LogEntryBase {
/**
* Set extra log parameters.
- * You can pass params to the log action message
- * by prefixing the keys with a number and colon.
- * The numbering should start with number 4, the
- * first three parameters are hardcoded for every
- * message. Example:
+ *
+ * You can pass params to the log action message by prefixing the keys with
+ * a number and optional type, using colons to separate the fields. The
+ * numbering should start with number 4, the first three parameters are
+ * hardcoded for every message. Example:
* $entry->setParameters(
- * '4:color' => 'blue',
+ * '4::color' => 'blue',
+ * '5:number:count' => 3000,
* 'animal' => 'dog'
* );
*
@@ -459,6 +463,16 @@ class ManualLogEntry extends LogEntryBase {
}
/**
+ * Set the 'legacy' flag
+ *
+ * @since 1.25
+ * @param bool $legacy
+ */
+ public function setLegacy( $legacy ) {
+ $this->legacy = $legacy;
+ }
+
+ /**
* TODO: document
*
* @since 1.19
@@ -533,10 +547,6 @@ class ManualLogEntry extends LogEntryBase {
$dbw->insert( 'log_search', $rows, __METHOD__, 'IGNORE' );
}
- // Update any bloom filter cache
- $member = $this->getTarget()->getNamespace() . ':' . $this->getTarget()->getDBkey();
- BloomCache::get( 'main' )->insert( wfWikiId(), 'TitleHasLogs', $member );
-
return $this->id;
}
@@ -640,6 +650,14 @@ class ManualLogEntry extends LogEntryBase {
return $this->comment;
}
+ /**
+ * @since 1.25
+ * @return bool
+ */
+ public function isLegacy() {
+ return $this->legacy;
+ }
+
public function getDeleted() {
return (int)$this->deleted;
}
diff --git a/includes/logging/LogEventsList.php b/includes/logging/LogEventsList.php
index 4dc25ef3..dfe31365 100644
--- a/includes/logging/LogEventsList.php
+++ b/includes/logging/LogEventsList.php
@@ -26,7 +26,7 @@
class LogEventsList extends ContextSource {
const NO_ACTION_LINK = 1;
const NO_EXTRA_USER_LINKS = 2;
- const USE_REVDEL_CHECKBOXES = 4;
+ const USE_CHECKBOXES = 4;
public $flags;
@@ -44,7 +44,7 @@ class LogEventsList extends ContextSource {
* a Skin object. Use of Skin is deprecated.
* @param null $unused Unused; used to be an OutputPage object.
* @param int $flags Can be a combination of self::NO_ACTION_LINK,
- * self::NO_EXTRA_USER_LINKS or self::USE_REVDEL_CHECKBOXES.
+ * self::NO_EXTRA_USER_LINKS or self::USE_CHECKBOXES.
*/
public function __construct( $context, $unused = null, $flags = 0 ) {
if ( $context instanceof IContextSource ) {
@@ -58,17 +58,6 @@ class LogEventsList extends ContextSource {
}
/**
- * Deprecated alias for getTitle(); do not use.
- *
- * @deprecated since 1.20; use getTitle() instead.
- * @return Title
- */
- public function getDisplayTitle() {
- wfDeprecated( __METHOD__, '1.20' );
- return $this->getTitle();
- }
-
- /**
* Show options for the log list
*
* @param array|string $types
@@ -234,7 +223,8 @@ class LogEventsList extends ContextSource {
'user',
'mw-log-user',
15,
- $user
+ $user,
+ array( 'class' => 'mw-autocomplete-user' )
);
return '<span style="white-space: nowrap">' . $label . '</span>';
@@ -271,14 +261,21 @@ class LogEventsList extends ContextSource {
* @return string
*/
private function getExtraInputs( $types ) {
- $offender = $this->getRequest()->getVal( 'offender' );
- $user = User::newFromName( $offender, false );
- if ( !$user || ( $user->getId() == 0 && !IP::isIPAddress( $offender ) ) ) {
- $offender = ''; // Blank field if invalid
- }
- if ( count( $types ) == 1 && $types[0] == 'suppress' ) {
- return Xml::inputLabel( $this->msg( 'revdelete-offender' )->text(), 'offender',
- 'mw-log-offender', 20, $offender );
+ if ( count( $types ) == 1 ) {
+ if ( $types[0] == 'suppress' ) {
+ $offender = $this->getRequest()->getVal( 'offender' );
+ $user = User::newFromName( $offender, false );
+ if ( !$user || ( $user->getId() == 0 && !IP::isIPAddress( $offender ) ) ) {
+ $offender = ''; // Blank field if invalid
+ }
+ return Xml::inputLabel( $this->msg( 'revdelete-offender' )->text(), 'offender',
+ 'mw-log-offender', 20, $offender );
+ } else {
+ // Allow extensions to add their own extra inputs
+ $input = '';
+ Hooks::run( 'LogEventsListGetExtraInputs', array( $types[0], $this, &$input ) );
+ return $input;
+ }
}
return '';
@@ -344,14 +341,27 @@ class LogEventsList extends ContextSource {
*/
private function getShowHideLinks( $row ) {
// We don't want to see the links and
+ if ( $this->flags == self::NO_ACTION_LINK ) {
+ return '';
+ }
+
+ $user = $this->getUser();
+
+ // If change tag editing is available to this user, return the checkbox
+ if ( $this->flags & self::USE_CHECKBOXES && ChangeTags::showTagEditingUI( $user ) ) {
+ return Xml::check(
+ 'showhiderevisions',
+ false,
+ array( 'name' => 'ids[' . $row->log_id . ']' )
+ );
+ }
+
// no one can hide items from the suppress log.
- if ( ( $this->flags == self::NO_ACTION_LINK )
- || $row->log_type == 'suppress'
- ) {
+ if ( $row->log_type == 'suppress' ) {
return '';
}
+
$del = '';
- $user = $this->getUser();
// Don't show useless checkbox to people who cannot hide log entries
if ( $user->isAllowed( 'deletedhistory' ) ) {
$canHide = $user->isAllowed( 'deletelogentry' );
@@ -361,7 +371,7 @@ class LogEventsList extends ContextSource {
$canViewThisSuppressedEntry = $canViewSuppressedOnly && $entryIsSuppressed;
if ( $row->log_deleted || $canHide ) {
// Show checkboxes instead of links.
- if ( $canHide && $this->flags & self::USE_REVDEL_CHECKBOXES && !$canViewThisSuppressedEntry ) {
+ if ( $canHide && $this->flags & self::USE_CHECKBOXES && !$canViewThisSuppressedEntry ) {
// If event was hidden from sysops
if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) {
$del = Xml::check( 'deleterevisions', false, array( 'disabled' => 'disabled' ) );
@@ -544,14 +554,16 @@ class LogEventsList extends ContextSource {
if ( $lim > 0 ) {
$pager->mLimit = $lim;
}
-
+ // Fetch the log rows and build the HTML if needed
$logBody = $pager->getBody();
+ $numRows = $pager->getNumRows();
+
$s = '';
if ( $logBody ) {
if ( $msgKey[0] ) {
$dir = $context->getLanguage()->getDir();
- $lang = $context->getLanguage()->getCode();
+ $lang = $context->getLanguage()->getHtmlCode();
$s = Xml::openElement( 'div', array(
'class' => "mw-warning-with-logexcerpt mw-content-$dir",
@@ -575,7 +587,7 @@ class LogEventsList extends ContextSource {
$context->msg( 'logempty' )->parse() );
}
- if ( $pager->getNumRows() > $pager->mLimit ) { # Show "Full log" link
+ if ( $numRows > $pager->mLimit ) { # Show "Full log" link
$urlParam = array();
if ( $page instanceof Title ) {
$urlParam['page'] = $page->getPrefixedDBkey();
@@ -613,7 +625,7 @@ class LogEventsList extends ContextSource {
}
/* hook can return false, if we don't want the message to be emitted (Wikia BugId:7093) */
- if ( wfRunHooks( 'LogEventsListShowLogExtract', array( &$s, $types, $page, $user, $param ) ) ) {
+ if ( Hooks::run( 'LogEventsListShowLogExtract', array( &$s, $types, $page, $user, $param ) ) ) {
// $out can be either an OutputPage object or a String-by-reference
if ( $out instanceof OutputPage ) {
$out->addHTML( $s );
@@ -622,7 +634,7 @@ class LogEventsList extends ContextSource {
}
}
- return $pager->getNumRows();
+ return $numRows;
}
/**
diff --git a/includes/logging/LogFormatter.php b/includes/logging/LogFormatter.php
index 48a565f2..9c2fdd35 100644
--- a/includes/logging/LogFormatter.php
+++ b/includes/logging/LogFormatter.php
@@ -25,9 +25,12 @@
/**
* Implements the default log formatting.
- * Can be overridden by subclassing and setting
- * $wgLogActionsHandlers['type/subtype'] = 'class'; or
- * $wgLogActionsHandlers['type/*'] = 'class';
+ *
+ * Can be overridden by subclassing and setting:
+ *
+ * $wgLogActionsHandlers['type/subtype'] = 'class'; or
+ * $wgLogActionsHandlers['type/*'] = 'class';
+ *
* @since 1.19
*/
class LogFormatter {
@@ -80,6 +83,9 @@ class LogFormatter {
/** @var int Constant for handling log_deleted */
protected $audience = self::FOR_PUBLIC;
+ /** @var IContextSource Context for logging */
+ public $context;
+
/** @var bool Whether to output user tool links */
protected $linkFlood = false;
@@ -322,6 +328,57 @@ class LogFormatter {
break;
}
break;
+
+ case 'merge':
+ $text = wfMessage( 'pagemerge-logentry' )
+ ->rawParams( $target, $parameters['4::dest'], $parameters['5::mergepoint'] )
+ ->inContentLanguage()->escaped();
+ break;
+
+ case 'block':
+ switch ( $entry->getSubtype() ) {
+ case 'block':
+ global $wgContLang;
+ // Keep compatibility with extensions by checking for
+ // new key (5::duration/6::flags) or old key (0/optional 1)
+ if ( $entry->isLegacy() ) {
+ $rawDuration = $parameters[0];
+ $rawFlags = isset( $parameters[1] ) ? $parameters[1] : '';
+ } else {
+ $rawDuration = $parameters['5::duration'];
+ $rawFlags = $parameters['6::flags'];
+ }
+ $duration = $wgContLang->translateBlockExpiry( $rawDuration );
+ $flags = BlockLogFormatter::formatBlockFlags( $rawFlags, $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 'import':
+ switch ( $entry->getSubtype() ) {
+ case 'upload':
+ $text = wfMessage( 'import-logentry-upload' )
+ ->rawParams( $target )->inContentLanguage()->escaped();
+ break;
+ case 'interwiki':
+ $text = wfMessage( 'import-logentry-interwiki' )
+ ->rawParams( $target )->inContentLanguage()->escaped();
+ break;
+ }
+ break;
// case 'suppress' --private log -- aaron (so we know who to blame in a few years :-D)
// default:
}
@@ -349,8 +406,10 @@ class LogFormatter {
$element = $this->styleRestricedElement( $element );
}
} else {
- $performer = $this->getPerformerElement() . $this->msg( 'word-separator' )->text();
- $element = $performer . $this->getRestrictedElement( 'rev-deleted-event' );
+ $sep = $this->msg( 'word-separator' );
+ $sep = $this->plaintext ? $sep->text() : $sep->escaped();
+ $performer = $this->getPerformerElement();
+ $element = $performer . $sep . $this->getRestrictedElement( 'rev-deleted-event' );
}
return $element;
@@ -413,7 +472,9 @@ class LogFormatter {
continue;
}
list( $index, $type, ) = explode( ':', $key, 3 );
- $params[$index - 1] = $this->formatParameterValue( $type, $value );
+ if ( ctype_digit( $index ) ) {
+ $params[$index - 1] = $this->formatParameterValue( $type, $value );
+ }
}
/* Message class doesn't like non consecutive numbering.
@@ -422,7 +483,8 @@ class LogFormatter {
*/
if ( count( $params ) ) {
$max = max( array_keys( $params ) );
- for ( $i = 4; $i < $max; $i++ ) {
+ // index 0 to 2 are added in getMessageParameters
+ for ( $i = 3; $i < $max; $i++ ) {
if ( !isset( $params[$i] ) ) {
$params[$i] = '';
}
@@ -480,8 +542,8 @@ class LogFormatter {
* * title-link: The value is a page title,
* returns link to this page
* * number: Format value as number
- * @param string $value The parameter value that should
- * be formated
+ * * list: Format value as a comma-separated list
+ * @param mixed $value The parameter value that should be formatted
* @return string|array Formated value
* @since 1.21
*/
@@ -492,6 +554,9 @@ class LogFormatter {
case 'raw':
$value = Message::rawParam( $value );
break;
+ case 'list':
+ $value = $this->context->getLanguage()->commaList( $value );
+ break;
case 'msg':
$value = $this->msg( $value )->text();
break;
@@ -629,7 +694,7 @@ class LogFormatter {
return $this->context->msg( $key );
}
- protected function makeUserLink( User $user ) {
+ protected function makeUserLink( User $user, $toolFlags = 0 ) {
if ( $this->plaintext ) {
$element = $user->getName();
} else {
@@ -639,9 +704,11 @@ class LogFormatter {
);
if ( $this->linkFlood ) {
- $element .= Linker::userToolLinksRedContribs(
+ $element .= Linker::userToolLinks(
$user->getId(),
$user->getName(),
+ true, // redContribsWhenNoEdits
+ $toolFlags,
$user->getEditCount()
);
}
@@ -666,6 +733,120 @@ class LogFormatter {
// problems with extensions
return $this->getMessageParameters();
}
+
+ /**
+ * Get the array of parameters, converted from legacy format if necessary.
+ * @since 1.25
+ * @return array
+ */
+ protected function getParametersForApi() {
+ return $this->entry->getParameters();
+ }
+
+ /**
+ * Format parameters for API output
+ *
+ * The result array should generally map named keys to values. Index and
+ * type should be omitted, e.g. "4::foo" should be returned as "foo" in the
+ * output. Values should generally be unformatted.
+ *
+ * Renames or removals of keys besides from the legacy numeric format to
+ * modern named style should be avoided. Any renames should be announced to
+ * the mediawiki-api-announce mailing list.
+ *
+ * @since 1.25
+ * @return array
+ */
+ public function formatParametersForApi() {
+ $logParams = array();
+ foreach ( $this->getParametersForApi() as $key => $value ) {
+ $vals = explode( ':', $key, 3 );
+ if ( count( $vals ) !== 3 ) {
+ $logParams[$key] = $value;
+ continue;
+ }
+ $logParams += $this->formatParameterValueForApi( $vals[2], $vals[1], $value );
+ }
+ ApiResult::setIndexedTagName( $logParams, 'param' );
+ ApiResult::setArrayType( $logParams, 'assoc' );
+
+ return $logParams;
+ }
+
+ /**
+ * Format a single parameter value for API output
+ *
+ * @since 1.25
+ * @param string $name
+ * @param string $type
+ * @param string $value
+ * @return array
+ */
+ protected function formatParameterValueForApi( $name, $type, $value ) {
+ $type = strtolower( trim( $type ) );
+ switch ( $type ) {
+ case 'bool':
+ $value = (bool)$value;
+ break;
+
+ case 'number':
+ if ( ctype_digit( $value ) ) {
+ $value = (int)$value;
+ } else {
+ $value = (float)$value;
+ }
+ break;
+
+ case 'array':
+ case 'assoc':
+ case 'kvp':
+ if ( is_array( $value ) ) {
+ ApiResult::setArrayType( $value, $type );
+ }
+ break;
+
+ case 'timestamp':
+ $value = wfTimestamp( TS_ISO_8601, $value );
+ break;
+
+ case 'msg':
+ case 'msg-content':
+ $msg = $this->msg( $value );
+ if ( $type === 'msg-content' ) {
+ $msg->inContentLanguage();
+ }
+ $value = array();
+ $value["{$name}_key"] = $msg->getKey();
+ if ( $msg->getParams() ) {
+ $value["{$name}_params"] = $msg->getParams();
+ }
+ $value["{$name}_text"] = $msg->text();
+ return $value;
+
+ case 'title':
+ case 'title-link':
+ $title = Title::newFromText( $value );
+ if ( $title ) {
+ $value = array();
+ ApiQueryBase::addTitleInfo( $value, $title, "{$name}_" );
+ }
+ return $value;
+
+ case 'user':
+ case 'user-link':
+ $user = User::newFromName( $value );
+ if ( $user ) {
+ $value = $user->getName();
+ }
+ break;
+
+ default:
+ // do nothing
+ break;
+ }
+
+ return array( $name => $value );
+ }
}
/**
@@ -725,7 +906,9 @@ class LegacyLogFormatter extends LogFormatter {
$performer = $this->getPerformerElement();
if ( !$this->irctext ) {
- $action = $performer . $this->msg( 'word-separator' )->text() . $action;
+ $sep = $this->msg( 'word-separator' );
+ $sep = $this->plaintext ? $sep->text() : $sep->escaped();
+ $action = $performer . $sep . $action;
}
return $action;
@@ -745,29 +928,7 @@ class LegacyLogFormatter extends LogFormatter {
$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(
@@ -791,26 +952,6 @@ class LegacyLogFormatter extends LogFormatter {
return $this->msg( 'parentheses' )->rawParams(
$this->context->getLanguage()->pipeList( $links ) )->escaped();
- // Show unmerge link
- } elseif ( $type == 'merge' && $subtype == 'merge' ) {
- if ( !$this->context->getUser()->isAllowed( 'mergehistory' ) ) {
- return '';
- }
-
- $params = $this->extractParameters();
- $revert = Linker::linkKnown(
- SpecialPage::getTitleFor( 'MergeHistory' ),
- $this->msg( 'revertmerge' )->escaped(),
- array(),
- array(
- 'target' => $params[3],
- 'dest' => $title->getPrefixedDBkey(),
- 'mergepoint' => $params[4],
- 'submitted' => 1 // show the revisions immediately
- )
- );
-
- return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
}
// Do nothing. The implementation is handled by the hook modifiying the
@@ -826,7 +967,7 @@ class LegacyLogFormatter extends LogFormatter {
$params = $this->entry->getParameters();
- wfRunHooks( 'LogLine', array( $type, $subtype, $title, $params,
+ Hooks::run( 'LogLine', array( $type, $subtype, $title, $params,
&$this->comment, &$this->revert, $this->entry->getTimestamp() ) );
return $this->revert;
diff --git a/includes/logging/LogPage.php b/includes/logging/LogPage.php
index ce5b972f..82e5808a 100644
--- a/includes/logging/LogPage.php
+++ b/includes/logging/LogPage.php
@@ -288,24 +288,8 @@ class LogPage {
$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 = '&lrm;' . 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]}" );
@@ -370,69 +354,22 @@ class LogPage {
return $title->getPrefixedText();
}
- switch ( $type ) {
- case 'move':
- $titleLink = Linker::link(
- $title,
- htmlspecialchars( $title->getPrefixedText() ),
- array(),
- array( 'redirect' => 'no' )
- );
-
- $targetTitle = Title::newFromText( $params[0] );
-
- if ( !$targetTitle ) {
- # Workaround for broken database
- $params[0] = htmlspecialchars( $params[0] );
- } else {
- $params[0] = Linker::link(
- $targetTitle,
- htmlspecialchars( $params[0] )
- );
- }
- break;
- 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;
- case 'merge':
- $titleLink = Linker::link(
- $title,
- $title->getPrefixedText(),
- array(),
- array( 'redirect' => 'no' )
- );
- $params[0] = Linker::link(
- Title::newFromText( $params[0] ),
- htmlspecialchars( $params[0] )
- );
- $params[1] = $lang->timeanddate( $params[1] );
- 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;
@@ -485,6 +422,10 @@ class LogPage {
$logEntry->setTarget( $target );
$logEntry->setPerformer( $doer );
$logEntry->setParameters( $params );
+ // All log entries using the LogPage to insert into the logging table
+ // are using the old logging system and therefore the legacy flag is
+ // needed to say the LogFormatter the parameters have numeric keys
+ $logEntry->setLegacy( true );
$formatter = LogFormatter::newFromEntry( $logEntry );
$context = RequestContext::newExtraneousContext( $target );
@@ -550,61 +491,6 @@ class LogPage {
}
/**
- * 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
* @since 1.19
diff --git a/includes/logging/LogPager.php b/includes/logging/LogPager.php
index 256934e4..bf489ab9 100644
--- a/includes/logging/LogPager.php
+++ b/includes/logging/LogPager.php
@@ -323,7 +323,6 @@ class LogPager extends ReverseChronologicalPager {
}
public function getStartBody() {
- wfProfileIn( __METHOD__ );
# Do a link batch query
if ( $this->getNumRows() > 0 ) {
$lb = new LinkBatch;
@@ -339,7 +338,6 @@ class LogPager extends ReverseChronologicalPager {
$lb->execute();
$this->mResult->seek( 0 );
}
- wfProfileOut( __METHOD__ );
return '';
}
diff --git a/includes/logging/MergeLogFormatter.php b/includes/logging/MergeLogFormatter.php
new file mode 100644
index 00000000..36e383b0
--- /dev/null
+++ b/includes/logging/MergeLogFormatter.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Formatter for merge 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 merge log entries.
+ *
+ * @since 1.25
+ */
+class MergeLogFormatter extends LogFormatter {
+ public function getPreloadTitles() {
+ $params = $this->extractParameters();
+
+ return array( Title::newFromText( $params[3] ) );
+ }
+
+ protected function getMessageParameters() {
+ $params = parent::getMessageParameters();
+ $oldname = $this->makePageLink( $this->entry->getTarget(), array( 'redirect' => 'no' ) );
+ $newname = $this->makePageLink( Title::newFromText( $params[3] ) );
+ $params[2] = Message::rawParam( $oldname );
+ $params[3] = Message::rawParam( $newname );
+ $params[4] = $this->context->getLanguage()
+ ->userTimeAndDate( $params[4], $this->context->getUser() );
+ return $params;
+ }
+
+ public function getActionLinks() {
+ if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
+ || !$this->context->getUser()->isAllowed( 'mergehistory' )
+ ) {
+ return '';
+ }
+
+ // Show unmerge link
+ $params = $this->extractParameters();
+ $revert = Linker::linkKnown(
+ SpecialPage::getTitleFor( 'MergeHistory' ),
+ $this->msg( 'revertmerge' )->escaped(),
+ array(),
+ array(
+ 'target' => $params[3],
+ 'dest' => $this->entry->getTarget()->getPrefixedDBkey(),
+ 'mergepoint' => $params[4],
+ 'submitted' => 1 // show the revisions immediately
+ )
+ );
+
+ return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
+ }
+
+ protected function getParametersForApi() {
+ $entry = $this->entry;
+ $params = $entry->getParameters();
+
+ static $map = array(
+ '4:title:dest',
+ '5:timestamp:mergepoint',
+ '4::dest' => '4:title:dest',
+ '5::mergepoint' => '5:timestamp:mergepoint',
+ );
+ foreach ( $map as $index => $key ) {
+ if ( isset( $params[$index] ) ) {
+ $params[$key] = $params[$index];
+ unset( $params[$index] );
+ }
+ }
+
+ return $params;
+ }
+}
diff --git a/includes/logging/MoveLogFormatter.php b/includes/logging/MoveLogFormatter.php
index 39130163..7f5e9efa 100644
--- a/includes/logging/MoveLogFormatter.php
+++ b/includes/logging/MoveLogFormatter.php
@@ -37,8 +37,9 @@ class MoveLogFormatter extends LogFormatter {
protected function getMessageKey() {
$key = parent::getMessageKey();
- $params = $this->getMessageParameters();
+ $params = $this->extractParameters();
if ( isset( $params[4] ) && $params[4] === '1' ) {
+ // Messages: logentry-move-move-noredirect, logentry-move-move_redir-noredirect
$key .= '-noredirect';
}
@@ -51,6 +52,7 @@ class MoveLogFormatter extends LogFormatter {
$newname = $this->makePageLink( Title::newFromText( $params[3] ) );
$params[2] = Message::rawParam( $oldname );
$params[3] = Message::rawParam( $newname );
+ unset( $params[4] ); // handled in getMessageKey
return $params;
}
@@ -83,4 +85,29 @@ class MoveLogFormatter extends LogFormatter {
return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
}
+
+ protected function getParametersForApi() {
+ $entry = $this->entry;
+ $params = $entry->getParameters();
+
+ static $map = array(
+ '4:title:target',
+ '5:bool:suppressredirect',
+ '4::target' => '4:title:target',
+ '5::noredir' => '5:bool:suppressredirect',
+ );
+ foreach ( $map as $index => $key ) {
+ if ( isset( $params[$index] ) ) {
+ $params[$key] = $params[$index];
+ unset( $params[$index] );
+ }
+ }
+
+ if ( !isset( $params['5:bool:suppressredirect'] ) ) {
+ $params['5:bool:suppressredirect'] = false;
+ }
+
+ return $params;
+ }
+
}
diff --git a/includes/logging/PatrolLogFormatter.php b/includes/logging/PatrolLogFormatter.php
index 2abaf173..00337432 100644
--- a/includes/logging/PatrolLogFormatter.php
+++ b/includes/logging/PatrolLogFormatter.php
@@ -62,4 +62,24 @@ class PatrolLogFormatter extends LogFormatter {
return $params;
}
+
+ protected function getParametersForApi() {
+ $entry = $this->entry;
+ $params = $entry->getParameters();
+
+ static $map = array(
+ '4::curid',
+ '5::previd',
+ '6:bool:auto',
+ '6::auto' => '6:bool:auto',
+ );
+ foreach ( $map as $index => $key ) {
+ if ( isset( $params[$index] ) ) {
+ $params[$key] = $params[$index];
+ unset( $params[$index] );
+ }
+ }
+
+ return $params;
+ }
}
diff --git a/includes/logging/RightsLogFormatter.php b/includes/logging/RightsLogFormatter.php
index ac252aeb..352bda58 100644
--- a/includes/logging/RightsLogFormatter.php
+++ b/includes/logging/RightsLogFormatter.php
@@ -67,20 +67,8 @@ class RightsLogFormatter extends LogFormatter {
return $params;
}
- $oldGroups = $params[3];
- $newGroups = $params[4];
-
- // Less old entries
- if ( $oldGroups === '' ) {
- $oldGroups = array();
- } elseif ( is_string( $oldGroups ) ) {
- $oldGroups = array_map( 'trim', explode( ',', $oldGroups ) );
- }
- if ( $newGroups === '' ) {
- $newGroups = array();
- } elseif ( is_string( $newGroups ) ) {
- $newGroups = array_map( 'trim', explode( ',', $newGroups ) );
- }
+ $oldGroups = $this->makeGroupArray( $params[3] );
+ $newGroups = $this->makeGroupArray( $params[4] );
$userName = $this->entry->getTarget()->getText();
if ( !$this->plaintext && count( $oldGroups ) ) {
@@ -110,4 +98,53 @@ class RightsLogFormatter extends LogFormatter {
return $params;
}
+
+ protected function getParametersForApi() {
+ $entry = $this->entry;
+ $params = $entry->getParameters();
+
+ static $map = array(
+ '4:array:oldgroups',
+ '5:array:newgroups',
+ '4::oldgroups' => '4:array:oldgroups',
+ '5::newgroups' => '5:array:newgroups',
+ );
+ foreach ( $map as $index => $key ) {
+ if ( isset( $params[$index] ) ) {
+ $params[$key] = $params[$index];
+ unset( $params[$index] );
+ }
+ }
+
+ // Really old entries does not have log params
+ if ( isset( $params['4:array:oldgroups'] ) ) {
+ $params['4:array:oldgroups'] = $this->makeGroupArray( $params['4:array:oldgroups'] );
+ }
+ if ( isset( $params['5:array:newgroups'] ) ) {
+ $params['5:array:newgroups'] = $this->makeGroupArray( $params['5:array:newgroups'] );
+ }
+
+ return $params;
+ }
+
+ public function formatParametersForApi() {
+ $ret = parent::formatParametersForApi();
+ if ( isset( $ret['oldgroups'] ) ) {
+ ApiResult::setIndexedTagName( $ret['oldgroups'], 'g' );
+ }
+ if ( isset( $ret['newgroups'] ) ) {
+ ApiResult::setIndexedTagName( $ret['newgroups'], 'g' );
+ }
+ return $ret;
+ }
+
+ private function makeGroupArray( $group ) {
+ // Migrate old group params from string to array
+ if ( $group === '' ) {
+ $group = array();
+ } elseif ( is_string( $group ) ) {
+ $group = array_map( 'trim', explode( ',', $group ) );
+ }
+ return $group;
+ }
}
diff --git a/includes/logging/TagLogFormatter.php b/includes/logging/TagLogFormatter.php
new file mode 100644
index 00000000..5a58c331
--- /dev/null
+++ b/includes/logging/TagLogFormatter.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * 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
+ */
+
+/**
+ * This class formats tag log entries.
+ *
+ * Parameters (one-based indexes):
+ * 4::revid
+ * 5::logid
+ * 6:list:tagsAdded
+ * 7:number:tagsAddedCount
+ * 8:list:tagsRemoved
+ * 9:number:tagsRemovedCount
+ *
+ * @since 1.25
+ */
+class TagLogFormatter extends LogFormatter {
+ protected function getMessageKey() {
+ $key = parent::getMessageKey();
+ $params = $this->getMessageParameters();
+
+ $add = ( isset( $params[6] ) && isset( $params[6]['num'] ) && $params[6]['num'] );
+ $remove = ( isset( $params[8] ) && isset( $params[8]['num'] ) && $params[8]['num'] );
+ $key .= ( $remove ? ( $add ? '' : '-remove' ) : '-add' );
+
+ if ( isset( $params[4] ) && $params[4] ) {
+ $key .= '-logentry';
+ } else {
+ $key .= '-revision';
+ }
+
+ return $key;
+ }
+}
diff --git a/includes/logging/UploadLogFormatter.php b/includes/logging/UploadLogFormatter.php
new file mode 100644
index 00000000..52961dc4
--- /dev/null
+++ b/includes/logging/UploadLogFormatter.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Formatter for upload 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 upload log entries.
+ *
+ * @since 1.25
+ */
+class UploadLogFormatter extends LogFormatter {
+
+ protected function getParametersForApi() {
+ $entry = $this->entry;
+ $params = $entry->getParameters();
+
+ static $map = array(
+ 'img_timestamp' => ':timestamp:img_timestamp',
+ );
+ foreach ( $map as $index => $key ) {
+ if ( isset( $params[$index] ) ) {
+ $params[$key] = $params[$index];
+ unset( $params[$index] );
+ }
+ }
+
+ return $params;
+ }
+
+}