summaryrefslogtreecommitdiff
path: root/includes/logging
diff options
context:
space:
mode:
Diffstat (limited to 'includes/logging')
-rw-r--r--includes/logging/DeleteLogFormatter.php196
-rw-r--r--includes/logging/LogEntry.php125
-rw-r--r--includes/logging/LogEventsList.php146
-rw-r--r--includes/logging/LogFormatter.php446
-rw-r--r--includes/logging/LogPage.php137
-rw-r--r--includes/logging/LogPager.php105
-rw-r--r--includes/logging/MoveLogFormatter.php82
-rw-r--r--includes/logging/NewUsersLogFormatter.php65
-rw-r--r--includes/logging/PatrolLog.php7
-rw-r--r--includes/logging/PatrolLogFormatter.php63
-rw-r--r--includes/logging/RightsLogFormatter.php112
11 files changed, 917 insertions, 567 deletions
diff --git a/includes/logging/DeleteLogFormatter.php b/includes/logging/DeleteLogFormatter.php
new file mode 100644
index 00000000..01528b7e
--- /dev/null
+++ b/includes/logging/DeleteLogFormatter.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * Formatter for delete 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
+ * @author Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ * @since 1.22
+ */
+
+/**
+ * This class formats delete log entries.
+ *
+ * @since 1.19
+ */
+class DeleteLogFormatter extends LogFormatter {
+ protected function getMessageKey() {
+ $key = parent::getMessageKey();
+ if ( in_array( $this->entry->getSubtype(), array( 'event', 'revision' ) ) ) {
+ if ( count( $this->getMessageParameters() ) < 5 ) {
+ return "$key-legacy";
+ }
+ }
+ return $key;
+ }
+
+ protected function getMessageParameters() {
+ if ( isset( $this->parsedParametersDeleteLog ) ) {
+ return $this->parsedParametersDeleteLog;
+ }
+
+ $params = parent::getMessageParameters();
+ $subtype = $this->entry->getSubtype();
+ if ( in_array( $subtype, array( 'event', 'revision' ) ) ) {
+ // $params[3] here is 'revision' for page revisions, 'oldimage' for file versions, or a comma-separated list of log_ids for log entries.
+ // $subtype here is 'revision' for page revisions and file versions, or 'event' for log entries.
+ if (
+ ( $subtype === 'event' && count( $params ) === 6 ) ||
+ ( $subtype === 'revision' && isset( $params[3] ) && ( $params[3] === 'revision' || $params[3] === 'oldimage' ) )
+ ) {
+ $paramStart = $subtype === 'revision' ? 4 : 3;
+
+ $old = $this->parseBitField( $params[$paramStart + 1] );
+ $new = $this->parseBitField( $params[$paramStart + 2] );
+ list( $hid, $unhid, $extra ) = RevisionDeleter::getChanges( $new, $old );
+ $changes = array();
+ foreach ( $hid as $v ) {
+ $changes[] = $this->msg( "$v-hid" )->plain();
+ }
+ foreach ( $unhid as $v ) {
+ $changes[] = $this->msg( "$v-unhid" )->plain();
+ }
+ foreach ( $extra as $v ) {
+ $changes[] = $this->msg( $v )->plain();
+ }
+ $changeText = $this->context->getLanguage()->listToText( $changes );
+
+ $newParams = array_slice( $params, 0, 3 );
+ $newParams[3] = $changeText;
+ $count = count( explode( ',', $params[$paramStart] ) );
+ $newParams[4] = $this->context->getLanguage()->formatNum( $count );
+ return $this->parsedParametersDeleteLog = $newParams;
+ } else {
+ return $this->parsedParametersDeleteLog = array_slice( $params, 0, 3 );
+ }
+ }
+
+ return $this->parsedParametersDeleteLog = $params;
+ }
+
+ protected function parseBitField( $string ) {
+ // Input is like ofield=2134 or just the number
+ if ( strpos( $string, 'field=' ) === 1 ) {
+ list( , $field ) = explode( '=', $string );
+ return (int)$field;
+ } else {
+ return (int)$string;
+ }
+ }
+
+ public function getActionLinks() {
+ $user = $this->context->getUser();
+ if ( !$user->isAllowed( 'deletedhistory' ) || $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) {
+ return '';
+ }
+
+ switch ( $this->entry->getSubtype() ) {
+ case 'delete': // Show undelete link
+ if ( $user->isAllowed( 'undelete' ) ) {
+ $message = 'undeletelink';
+ } else {
+ $message = 'undeleteviewlink';
+ }
+ $revert = Linker::linkKnown(
+ SpecialPage::getTitleFor( 'Undelete' ),
+ $this->msg( $message )->escaped(),
+ array(),
+ array( 'target' => $this->entry->getTarget()->getPrefixedDBkey() )
+ );
+ return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
+
+ case 'revision': // If an edit was hidden from a page give a review link to the history
+ $params = $this->extractParameters();
+ if ( !isset( $params[3] ) || !isset( $params[4] ) ) {
+ return '';
+ }
+
+ // Different revision types use different URL params...
+ $key = $params[3];
+ // This is a CSV of the IDs
+ $ids = explode( ',', $params[4] );
+
+ $links = array();
+
+ // If there's only one item, we can show a diff link
+ if ( count( $ids ) == 1 ) {
+ // Live revision diffs...
+ if ( $key == 'oldid' || $key == 'revision' ) {
+ $links[] = Linker::linkKnown(
+ $this->entry->getTarget(),
+ $this->msg( 'diff' )->escaped(),
+ array(),
+ array(
+ 'diff' => intval( $ids[0] ),
+ 'unhide' => 1
+ )
+ );
+ // Deleted revision diffs...
+ } elseif ( $key == 'artimestamp' || $key == 'archive' ) {
+ $links[] = Linker::linkKnown(
+ SpecialPage::getTitleFor( 'Undelete' ),
+ $this->msg( 'diff' )->escaped(),
+ array(),
+ array(
+ 'target' => $this->entry->getTarget()->getPrefixedDBkey(),
+ 'diff' => 'prev',
+ 'timestamp' => $ids[0]
+ )
+ );
+ }
+ }
+
+ // View/modify link...
+ $links[] = Linker::linkKnown(
+ SpecialPage::getTitleFor( 'Revisiondelete' ),
+ $this->msg( 'revdel-restore' )->escaped(),
+ array(),
+ array(
+ 'target' => $this->entry->getTarget()->getPrefixedText(),
+ 'type' => $key,
+ 'ids' => implode( ',', $ids ),
+ )
+ );
+
+ return $this->msg( 'parentheses' )->rawParams(
+ $this->context->getLanguage()->pipeList( $links ) )->escaped();
+
+ case 'event': // Hidden log items, give review link
+ $params = $this->extractParameters();
+ if ( !isset( $params[3] ) ) {
+ return '';
+ }
+ // This is a CSV of the IDs
+ $query = $params[3];
+ // Link to each hidden object ID, $params[1] is the url param
+ $revert = Linker::linkKnown(
+ SpecialPage::getTitleFor( 'Revisiondelete' ),
+ $this->msg( 'revdel-restore' )->escaped(),
+ array(),
+ array(
+ 'target' => $this->entry->getTarget()->getPrefixedText(),
+ 'type' => 'logging',
+ 'ids' => $query
+ )
+ );
+ return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
+ default:
+ return '';
+ }
+ }
+}
diff --git a/includes/logging/LogEntry.php b/includes/logging/LogEntry.php
index 37560d80..b2a8e50d 100644
--- a/includes/logging/LogEntry.php
+++ b/includes/logging/LogEntry.php
@@ -151,7 +151,7 @@ class DatabaseLogEntry extends LogEntryBase {
return array(
'tables' => $tables,
'fields' => $fields,
- 'conds' => array(),
+ 'conds' => array(),
'options' => array(),
'join_conds' => $joins,
);
@@ -165,7 +165,7 @@ class DatabaseLogEntry extends LogEntryBase {
*/
public static function newFromRow( $row ) {
if ( is_array( $row ) && isset( $row['rc_logid'] ) ) {
- return new RCDatabaseLogEntry( (object) $row );
+ return new RCDatabaseLogEntry( (object)$row );
} else {
return new self( $row );
}
@@ -175,6 +175,7 @@ class DatabaseLogEntry extends LogEntryBase {
/// Database result row.
protected $row;
+ protected $performer;
protected function __construct( $row ) {
$this->row = $row;
@@ -232,17 +233,20 @@ class DatabaseLogEntry extends LogEntryBase {
}
public function getPerformer() {
- $userId = (int) $this->row->log_user;
- if ( $userId !== 0 ) { // logged-in users
- if ( isset( $this->row->user_name ) ) {
- return User::newFromRow( $this->row );
- } else {
- return User::newFromId( $userId );
+ if ( !$this->performer ) {
+ $userId = (int)$this->row->log_user;
+ if ( $userId !== 0 ) { // logged-in users
+ if ( isset( $this->row->user_name ) ) {
+ $this->performer = User::newFromRow( $this->row );
+ } else {
+ $this->performer = User::newFromId( $userId );
+ }
+ } else { // IP users
+ $userText = $this->row->log_user_text;
+ $this->performer = User::newFromName( $userText, false );
}
- } else { // IP users
- $userText = $this->row->log_user_text;
- return User::newFromName( $userText, false );
}
+ return $this->performer;
}
public function getTarget() {
@@ -287,14 +291,17 @@ class RCDatabaseLogEntry extends DatabaseLogEntry {
}
public function getPerformer() {
- $userId = (int) $this->row->rc_user;
- if ( $userId !== 0 ) {
- return User::newFromId( $userId );
- } else {
- $userText = $this->row->rc_user_text;
- // Might be an IP, don't validate the username
- return User::newFromName( $userText, false );
+ if ( !$this->performer ) {
+ $userId = (int)$this->row->rc_user;
+ if ( $userId !== 0 ) {
+ $this->performer = User::newFromId( $userId );
+ } else {
+ $userText = $this->row->rc_user_text;
+ // Might be an IP, don't validate the username
+ $this->performer = User::newFromName( $userText, false );
+ }
}
+ return $this->performer;
}
public function getTarget() {
@@ -327,6 +334,7 @@ class ManualLogEntry extends LogEntryBase {
protected $type; ///!< @var string
protected $subtype; ///!< @var string
protected $parameters = array(); ///!< @var array
+ protected $relations = array(); ///!< @var array
protected $performer; ///!< @var User
protected $target; ///!< @var Title
protected $timestamp; ///!< @var string
@@ -335,9 +343,9 @@ class ManualLogEntry extends LogEntryBase {
/**
* Constructor.
- *
+ *
* @since 1.19
- *
+ *
* @param string $type
* @param string $subtype
*/
@@ -357,20 +365,31 @@ class ManualLogEntry extends LogEntryBase {
* '4:color' => 'blue',
* 'animal' => 'dog'
* );
- *
+ *
* @since 1.19
- *
- * @param $parameters array Associative array
+ *
+ * @param array $parameters Associative array
*/
public function setParameters( $parameters ) {
$this->parameters = $parameters;
}
/**
+ * Declare arbitrary tag/value relations to this log entry.
+ * These can be used to filter log entries later on.
+ *
+ * @param array Map of (tag => (list of values))
+ * @since 1.22
+ */
+ public function setRelations( array $relations ) {
+ $this->relations = $relations;
+ }
+
+ /**
* Set the user that performed the action being logged.
- *
+ *
* @since 1.19
- *
+ *
* @param User $performer
*/
public function setPerformer( User $performer ) {
@@ -379,9 +398,9 @@ class ManualLogEntry extends LogEntryBase {
/**
* Set the title of the object changed.
- *
+ *
* @since 1.19
- *
+ *
* @param Title $target
*/
public function setTarget( Title $target ) {
@@ -390,9 +409,9 @@ class ManualLogEntry extends LogEntryBase {
/**
* Set the timestamp of when the logged action took place.
- *
+ *
* @since 1.19
- *
+ *
* @param string $timestamp
*/
public function setTimestamp( $timestamp ) {
@@ -401,9 +420,9 @@ class ManualLogEntry extends LogEntryBase {
/**
* Set a comment associated with the action being logged.
- *
+ *
* @since 1.19
- *
+ *
* @param string $comment
*/
public function setComment( $comment ) {
@@ -412,9 +431,9 @@ class ManualLogEntry extends LogEntryBase {
/**
* TODO: document
- *
+ *
* @since 1.19
- *
+ *
* @param integer $deleted
*/
public function setDeleted( $deleted ) {
@@ -423,20 +442,24 @@ class ManualLogEntry extends LogEntryBase {
/**
* Inserts the entry into the logging table.
+ * @param IDatabase $dbw
* @return int If of the log entry
*/
- public function insert() {
+ public function insert( IDatabase $dbw = null ) {
global $wgContLang;
- $dbw = wfGetDB( DB_MASTER );
+ $dbw = $dbw ?: wfGetDB( DB_MASTER );
$id = $dbw->nextSequenceValue( 'logging_log_id_seq' );
if ( $this->timestamp === null ) {
$this->timestamp = wfTimestampNow();
}
+ # Trim spaces on user supplied text
+ $comment = trim( $this->getComment() );
+
# Truncate for whole multibyte characters.
- $comment = $wgContLang->truncate( $this->getComment(), 255 );
+ $comment = $wgContLang->truncate( $comment, 255 );
$data = array(
'log_id' => $id,
@@ -449,17 +472,35 @@ class ManualLogEntry extends LogEntryBase {
'log_title' => $this->getTarget()->getDBkey(),
'log_page' => $this->getTarget()->getArticleID(),
'log_comment' => $comment,
- 'log_params' => serialize( (array) $this->getParameters() ),
+ 'log_params' => serialize( (array)$this->getParameters() ),
);
$dbw->insert( 'logging', $data, __METHOD__ );
$this->id = !is_null( $id ) ? $id : $dbw->insertId();
+
+ $rows = array();
+ foreach ( $this->relations as $tag => $values ) {
+ if ( !strlen( $tag ) ) {
+ throw new MWException( "Got empty log search tag." );
+ }
+ foreach ( $values as $value ) {
+ $rows[] = array(
+ 'ls_field' => $tag,
+ 'ls_value' => $value,
+ 'ls_log_id' => $this->id
+ );
+ }
+ }
+ if ( count( $rows ) ) {
+ $dbw->insert( 'log_search', $rows, __METHOD__, 'IGNORE' );
+ }
+
return $this->id;
}
/**
* Publishes the log entry.
- * @param $newId int id of the log entry.
- * @param $to string: rcandudp (default), rc, udp
+ * @param int $newId id of the log entry.
+ * @param string $to rcandudp (default), rc, udp
*/
public function publish( $newId, $to = 'rcandudp' ) {
$log = new LogPage( $this->getType() );
@@ -493,7 +534,7 @@ class ManualLogEntry extends LogEntryBase {
$this->getSubtype(),
$this->getTarget(),
$this->getComment(),
- serialize( (array) $this->getParameters() ),
+ serialize( (array)$this->getParameters() ),
$newId,
$formatter->getIRCActionComment() // Used for IRC feeds
);
@@ -503,7 +544,7 @@ class ManualLogEntry extends LogEntryBase {
}
if ( $to === 'udp' || $to === 'rcandudp' ) {
- $rc->notifyRC2UDP();
+ $rc->notifyRCFeeds();
}
}
@@ -545,7 +586,7 @@ class ManualLogEntry extends LogEntryBase {
}
public function getDeleted() {
- return (int) $this->deleted;
+ return (int)$this->deleted;
}
}
diff --git a/includes/logging/LogEventsList.php b/includes/logging/LogEventsList.php
index 4de1a974..c27b57af 100644
--- a/includes/logging/LogEventsList.php
+++ b/includes/logging/LogEventsList.php
@@ -42,7 +42,7 @@ class LogEventsList extends ContextSource {
*
* @param $context IContextSource Context to use; formerly it was Skin object.
* @param $unused void Unused; used to be an OutputPage object.
- * @param $flags int flags; can be a combinaison of self::NO_ACTION_LINK,
+ * @param int $flags flags; can be a combinaison of self::NO_ACTION_LINK,
* self::NO_EXTRA_USER_LINKS or self::USE_REVDEL_CHECKBOXES.
*/
public function __construct( $context, $unused = null, $flags = 0 ) {
@@ -74,9 +74,9 @@ class LogEventsList extends ContextSource {
public function showHeader( $type ) {
wfDeprecated( __METHOD__, '1.19' );
// If only one log type is used, then show a special message...
- $headerType = (count($type) == 1) ? $type[0] : '';
+ $headerType = count( $type ) == 1 ? $type[0] : '';
$out = $this->getOutput();
- if( LogPage::isLogType( $headerType ) ) {
+ if ( LogPage::isLogType( $headerType ) ) {
$page = new LogPage( $headerType );
$out->setPageTitle( $page->getName()->text() );
$out->addHTML( $page->getDescription()->parseAsBlock() );
@@ -88,7 +88,7 @@ class LogEventsList extends ContextSource {
/**
* Show options for the log list
*
- * @param $types string or Array
+ * @param string $types or Array
* @param $user String
* @param $page String
* @param $pattern String
@@ -97,14 +97,14 @@ class LogEventsList extends ContextSource {
* @param $filter: array
* @param $tagFilter: array?
*/
- public function showOptions( $types=array(), $user='', $page='', $pattern='', $year='',
- $month = '', $filter = null, $tagFilter='' ) {
+ public function showOptions( $types = array(), $user = '', $page = '', $pattern = '', $year = '',
+ $month = '', $filter = null, $tagFilter = '' ) {
global $wgScript, $wgMiserMode;
$title = SpecialPage::getTitleFor( 'Log' );
// For B/C, we take strings, but make sure they are converted...
- $types = ($types === '') ? array() : (array)$types;
+ $types = ( $types === '' ) ? array() : (array)$types;
$tagSelector = ChangeTags::buildTagFilterSelector( $tagFilter );
@@ -117,7 +117,7 @@ class LogEventsList extends ContextSource {
$html .= $this->getExtraInputs( $types ) . "\n";
// Title pattern, if allowed
- if (!$wgMiserMode) {
+ if ( !$wgMiserMode ) {
$html .= $this->getTitlePattern( $pattern ) . "\n";
}
@@ -125,12 +125,12 @@ class LogEventsList extends ContextSource {
$html .= Xml::tags( 'p', null, Xml::dateMenu( $year, $month ) );
// Tag filter
- if ($tagSelector) {
+ if ( $tagSelector ) {
$html .= Xml::tags( 'p', null, implode( '&#160;', $tagSelector ) );
}
// Filter links
- if ($filter) {
+ if ( $filter ) {
$html .= Xml::tags( 'p', null, $this->getFilterLinks( $filter ) );
}
@@ -156,13 +156,13 @@ class LogEventsList extends ContextSource {
// Option value -> message mapping
$links = array();
$hiddens = ''; // keep track for "go" button
- foreach( $filter as $type => $val ) {
+ foreach ( $filter as $type => $val ) {
// Should the below assignment be outside the foreach?
// Then it would have to be copied. Not certain what is more expensive.
$query = $this->getDefaultQuery();
$queryKey = "hide_{$type}_log";
- $hideVal = 1 - intval($val);
+ $hideVal = 1 - intval( $val );
$query[$queryKey] = $hideVal;
$link = Linker::linkKnown(
@@ -172,11 +172,12 @@ class LogEventsList extends ContextSource {
$query
);
+ // Message: log-show-hide-patrol
$links[$type] = $this->msg( "log-show-hide-{$type}" )->rawParams( $link )->escaped();
$hiddens .= Html::hidden( "hide_{$type}_log", $val ) . "\n";
}
// Build links
- return '<small>'.$this->getLanguage()->pipeList( $links ) . '</small>' . $hiddens;
+ return '<small>' . $this->getLanguage()->pipeList( $links ) . '</small>' . $hiddens;
}
private function getDefaultQuery() {
@@ -198,7 +199,7 @@ class LogEventsList extends ContextSource {
* @return String: Formatted HTML
*/
private function getTypeMenu( $queryTypes ) {
- $queryType = count($queryTypes) == 1 ? $queryTypes[0] : '';
+ $queryType = count( $queryTypes ) == 1 ? $queryTypes[0] : '';
$selector = $this->getTypeSelector();
$selector->setDefault( $queryType );
return $selector->getHtml();
@@ -212,7 +213,7 @@ class LogEventsList extends ContextSource {
public function getTypeSelector() {
$typesByName = array(); // Temporary array
// First pass to load the log names
- foreach( LogPage::validTypes() as $type ) {
+ foreach ( LogPage::validTypes() as $type ) {
$page = new LogPage( $type );
$restriction = $page->getRestriction();
if ( $this->getUser()->isAllowed( $restriction ) ) {
@@ -221,7 +222,7 @@ class LogEventsList extends ContextSource {
}
// Second pass to sort by name
- asort($typesByName);
+ asort( $typesByName );
// Always put "All public logs" on top
$public = $typesByName[''];
@@ -229,7 +230,7 @@ class LogEventsList extends ContextSource {
$typesByName = array( '' => $public ) + $typesByName;
$select = new XmlSelect( 'type' );
- foreach( $typesByName as $type => $name ) {
+ foreach ( $typesByName as $type => $name ) {
$select->addOption( $name, $type );
}
@@ -273,10 +274,10 @@ class LogEventsList extends ContextSource {
private function getExtraInputs( $types ) {
$offender = $this->getRequest()->getVal( 'offender' );
$user = User::newFromName( $offender, false );
- if( !$user || ($user->getId() == 0 && !IP::isIPAddress($offender) ) ) {
+ if ( !$user || ( $user->getId() == 0 && !IP::isIPAddress( $offender ) ) ) {
$offender = ''; // Blank field if invalid
}
- if( count($types) == 1 && $types[0] == 'suppress' ) {
+ if ( count( $types ) == 1 && $types[0] == 'suppress' ) {
return Xml::inputLabel( $this->msg( 'revdelete-offender' )->text(), 'offender',
'mw-log-offender', 20, $offender );
}
@@ -307,7 +308,6 @@ class LogEventsList extends ContextSource {
$formatter->setContext( $this->getContext() );
$formatter->setShowUserToolLinks( !( $this->flags & self::NO_EXTRA_USER_LINKS ) );
- $title = $entry->getTarget();
$time = htmlspecialchars( $this->getLanguage()->userTimeAndDate(
$entry->getTimestamp(), $this->getUser() ) );
@@ -343,17 +343,17 @@ class LogEventsList extends ContextSource {
* @return string
*/
private function getShowHideLinks( $row ) {
- if( ( $this->flags == self::NO_ACTION_LINK ) // we don't want to see the links
+ if ( ( $this->flags == self::NO_ACTION_LINK ) // we don't want to see the links
|| $row->log_type == 'suppress' ) { // no one can hide items from the suppress log
return '';
}
$del = '';
$user = $this->getUser();
// Don't show useless checkbox to people who cannot hide log entries
- if( $user->isAllowed( 'deletedhistory' ) ) {
- if( $row->log_deleted || $user->isAllowed( 'deletelogentry' ) ) {
- $canHide = $user->isAllowed( 'deletelogentry' );
- if ( $this->flags & self::USE_REVDEL_CHECKBOXES ) { // Show checkboxes instead of links.
+ if ( $user->isAllowed( 'deletedhistory' ) ) {
+ $canHide = $user->isAllowed( 'deletelogentry' );
+ if ( $row->log_deleted || $canHide ) {
+ if ( $canHide && $this->flags & self::USE_REVDEL_CHECKBOXES ) { // Show checkboxes instead of links.
if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) { // If event was hidden from sysops
$del = Xml::check( 'deleterevisions', false, array( 'disabled' => 'disabled' ) );
} else {
@@ -365,8 +365,8 @@ class LogEventsList extends ContextSource {
} else {
$query = array(
'target' => SpecialPage::getTitleFor( 'Log', $row->log_type )->getPrefixedDBkey(),
- 'type' => 'logging',
- 'ids' => $row->log_id,
+ 'type' => 'logging',
+ 'ids' => $row->log_id,
);
$del = Linker::revDeleteLink( $query, self::isDeleted( $row, LogPage::DELETED_RESTRICTED ), $canHide );
}
@@ -383,13 +383,13 @@ class LogEventsList extends ContextSource {
* @param $right string
* @return Boolean
*/
- public static function typeAction( $row, $type, $action, $right='' ) {
- $match = is_array($type) ?
+ public static function typeAction( $row, $type, $action, $right = '' ) {
+ $match = is_array( $type ) ?
in_array( $row->log_type, $type ) : $row->log_type == $type;
- if( $match ) {
+ if ( $match ) {
$match = is_array( $action ) ?
in_array( $row->log_action, $action ) : $row->log_action == $action;
- if( $match && $right ) {
+ if ( $match && $right ) {
global $wgUser;
$match = $wgUser->isAllowed( $right );
}
@@ -420,7 +420,7 @@ class LogEventsList extends ContextSource {
* @return Boolean
*/
public static function userCanBitfield( $bitfield, $field, User $user = null ) {
- if( $bitfield & $field ) {
+ if ( $bitfield & $field ) {
if ( $bitfield & LogPage::DELETED_RESTRICTED ) {
$permission = 'suppressrevision';
} else {
@@ -450,10 +450,10 @@ class LogEventsList extends ContextSource {
* Show log extract. Either with text and a box (set $msgKey) or without (don't set $msgKey)
*
* @param $out OutputPage|String-by-reference
- * @param $types String|Array Log types to show
- * @param $page String|Title The page title to show log entries for
- * @param $user String The user who made the log entries
- * @param $param array Associative Array with the following additional options:
+ * @param string|array $types Log types to show
+ * @param string|Title $page The page title to show log entries for
+ * @param string $user The user who made the log entries
+ * @param array $param Associative Array with the following additional options:
* - lim Integer Limit of items to show, default is 50
* - conds Array Extra conditions for the query (e.g. "log_action != 'revision'")
* - showIfEmpty boolean Set to false if you don't want any output in case the loglist is empty
@@ -465,18 +465,20 @@ class LogEventsList extends ContextSource {
* set to '' to unset offset
* - wrap String Wrap the message in html (usually something like "<div ...>$1</div>").
* - flags Integer display flags (NO_ACTION_LINK,NO_EXTRA_USER_LINKS)
+ * - useRequestParams boolean Set true to use Pager-related parameters in the WebRequest
* @return Integer Number of total log items (not limited by $lim)
*/
public static function showLogExtract(
- &$out, $types=array(), $page='', $user='', $param = array()
+ &$out, $types = array(), $page = '', $user = '', $param = array()
) {
$defaultParameters = array(
'lim' => 25,
'conds' => array(),
'showIfEmpty' => true,
- 'msgKey' => array(''),
+ 'msgKey' => array( '' ),
'wrap' => "$1",
- 'flags' => 0
+ 'flags' => 0,
+ 'useRequestParams' => false,
);
# The + operator appends elements of remaining keys from the right
# handed array to the left handed, whereas duplicated keys are NOT overwritten.
@@ -488,6 +490,7 @@ class LogEventsList extends ContextSource {
$msgKey = $param['msgKey'];
$wrap = $param['wrap'];
$flags = $param['flags'];
+ $useRequestParams = $param['useRequestParams'];
if ( !is_array( $msgKey ) ) {
$msgKey = array( $msgKey );
}
@@ -501,13 +504,22 @@ class LogEventsList extends ContextSource {
# Insert list of top 50 (or top $lim) items
$loglist = new LogEventsList( $context, null, $flags );
$pager = new LogPager( $loglist, $types, $user, $page, '', $conds );
+ if ( !$useRequestParams ) {
+ # Reset vars that may have been taken from the request
+ $pager->mLimit = 50;
+ $pager->mDefaultLimit = 50;
+ $pager->mOffset = "";
+ $pager->mIsBackwards = false;
+ }
if ( isset( $param['offset'] ) ) { # Tell pager to ignore WebRequest offset
$pager->setOffset( $param['offset'] );
}
- if( $lim > 0 ) $pager->mLimit = $lim;
+ if ( $lim > 0 ) {
+ $pager->mLimit = $lim;
+ }
$logBody = $pager->getBody();
$s = '';
- if( $logBody ) {
+ if ( $logBody ) {
if ( $msgKey[0] ) {
$s = '<div class="mw-warning-with-logexcerpt">';
@@ -520,28 +532,29 @@ class LogEventsList extends ContextSource {
}
}
$s .= $loglist->beginLogEventsList() .
- $logBody .
- $loglist->endLogEventsList();
- } else {
- if ( $showIfEmpty ) {
- $s = Html::rawElement( 'div', array( 'class' => 'mw-warning-logempty' ),
- $context->msg( 'logempty' )->parse() );
- }
+ $logBody .
+ $loglist->endLogEventsList();
+ } elseif ( $showIfEmpty ) {
+ $s = Html::rawElement( 'div', array( 'class' => 'mw-warning-logempty' ),
+ $context->msg( 'logempty' )->parse() );
}
- if( $pager->getNumRows() > $pager->mLimit ) { # Show "Full log" link
+ if ( $pager->getNumRows() > $pager->mLimit ) { # Show "Full log" link
$urlParam = array();
if ( $page instanceof Title ) {
$urlParam['page'] = $page->getPrefixedDBkey();
} elseif ( $page != '' ) {
$urlParam['page'] = $page;
}
- if ( $user != '')
+ if ( $user != '' ) {
$urlParam['user'] = $user;
- if ( !is_array( $types ) ) # Make it an array, if it isn't
+ }
+ if ( !is_array( $types ) ) { # Make it an array, if it isn't
$types = array( $types );
+ }
# If there is exactly one log type, we can link to Special:Log?type=foo
- if ( count( $types ) == 1 )
+ if ( count( $types ) == 1 ) {
$urlParam['type'] = $types[0];
+ }
$s .= Linker::link(
SpecialPage::getTitleFor( 'Log' ),
$context->msg( 'log-fulllog' )->escaped(),
@@ -560,7 +573,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 ) ) ) {
// $out can be either an OutputPage object or a String-by-reference
- if ( $out instanceof OutputPage ){
+ if ( $out instanceof OutputPage ) {
$out->addHTML( $s );
} else {
$out = $s;
@@ -575,24 +588,31 @@ class LogEventsList extends ContextSource {
*
* @param $db DatabaseBase
* @param $audience string, public/user
+ * @param $user User object to check, or null to use $wgUser
* @return Mixed: string or false
*/
- public static function getExcludeClause( $db, $audience = 'public' ) {
- global $wgLogRestrictions, $wgUser;
+ public static function getExcludeClause( $db, $audience = 'public', User $user = null ) {
+ global $wgLogRestrictions;
+
+ if ( $audience != 'public' && $user === null ) {
+ global $wgUser;
+ $user = $wgUser;
+ }
+
// Reset the array, clears extra "where" clauses when $par is used
$hiddenLogs = array();
+
// Don't show private logs to unprivileged users
- foreach( $wgLogRestrictions as $logType => $right ) {
- if( $audience == 'public' || !$wgUser->isAllowed($right) ) {
- $safeType = $db->strencode( $logType );
- $hiddenLogs[] = $safeType;
+ foreach ( $wgLogRestrictions as $logType => $right ) {
+ if ( $audience == 'public' || !$user->isAllowed( $right ) ) {
+ $hiddenLogs[] = $logType;
}
}
- if( count($hiddenLogs) == 1 ) {
+ if ( count( $hiddenLogs ) == 1 ) {
return 'log_type != ' . $db->addQuotes( $hiddenLogs[0] );
- } elseif( $hiddenLogs ) {
- return 'log_type NOT IN (' . $db->makeList($hiddenLogs) . ')';
+ } elseif ( $hiddenLogs ) {
+ return 'log_type NOT IN (' . $db->makeList( $hiddenLogs ) . ')';
}
return false;
}
- }
+}
diff --git a/includes/logging/LogFormatter.php b/includes/logging/LogFormatter.php
index 7586bb65..8f60aee1 100644
--- a/includes/logging/LogFormatter.php
+++ b/includes/logging/LogFormatter.php
@@ -192,18 +192,18 @@ class LogFormatter {
$parameters = $entry->getParameters();
// @see LogPage::actionText()
// Text of title the action is aimed at.
- $target = $entry->getTarget()->getPrefixedText() ;
+ $target = $entry->getTarget()->getPrefixedText();
$text = null;
- switch( $entry->getType() ) {
+ switch ( $entry->getType() ) {
case 'move':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'move':
- $movesource = $parameters['4::target'];
+ $movesource = $parameters['4::target'];
$text = wfMessage( '1movedto2' )
->rawParams( $target, $movesource )->inContentLanguage()->escaped();
break;
case 'move_redir':
- $movesource = $parameters['4::target'];
+ $movesource = $parameters['4::target'];
$text = wfMessage( '1movedto2_redir' )
->rawParams( $target, $movesource )->inContentLanguage()->escaped();
break;
@@ -215,7 +215,7 @@ class LogFormatter {
break;
case 'delete':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'delete':
$text = wfMessage( 'deletedarticle' )
->rawParams( $target )->inContentLanguage()->escaped();
@@ -246,7 +246,7 @@ class LogFormatter {
break;
case 'protect':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'protect':
$text = wfMessage( 'protectedarticle' )
->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped();
@@ -263,13 +263,14 @@ class LogFormatter {
break;
case 'newusers':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'newusers':
case 'create':
$text = wfMessage( 'newuserlog-create-entry' )
->inContentLanguage()->escaped();
break;
case 'create2':
+ case 'byemail':
$text = wfMessage( 'newuserlog-create2-entry' )
->rawParams( $target )->inContentLanguage()->escaped();
break;
@@ -281,7 +282,7 @@ class LogFormatter {
break;
case 'upload':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'upload':
$text = wfMessage( 'uploadedimage' )
->rawParams( $target )->inContentLanguage()->escaped();
@@ -293,11 +294,33 @@ class LogFormatter {
}
break;
+ case 'rights':
+ if ( count( $parameters['4::oldgroups'] ) ) {
+ $oldgroups = implode( ', ', $parameters['4::oldgroups'] );
+ } else {
+ $oldgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped();
+ }
+ if ( count( $parameters['5::newgroups'] ) ) {
+ $newgroups = implode( ', ', $parameters['5::newgroups'] );
+ } else {
+ $newgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped();
+ }
+ switch ( $entry->getSubtype() ) {
+ case 'rights':
+ $text = wfMessage( 'rightslogentry' )
+ ->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped();
+ break;
+ case 'autopromote':
+ $text = wfMessage( 'rightslogentry-autopromote' )
+ ->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped();
+ break;
+ }
+ break;
// case 'suppress' --private log -- aaron (sign your messages so we know who to blame in a few years :-D)
// default:
}
- if( is_null( $text ) ) {
+ if ( is_null( $text ) ) {
$text = $this->getPlainActionText();
}
@@ -379,9 +402,11 @@ class LogFormatter {
// Filter out parameters which are not in format #:foo
foreach ( $entry->getParameters() as $key => $value ) {
- if ( strpos( $key, ':' ) === false ) continue;
- list( $index, $type, $name ) = explode( ':', $key, 3 );
- $params[$index - 1] = $value;
+ if ( strpos( $key, ':' ) === false ) {
+ continue;
+ }
+ list( $index, $type, ) = explode( ':', $key, 3 );
+ $params[$index - 1] = $this->formatParameterValue( $type, $value );
}
/* Message class doesn't like non consecutive numbering.
@@ -416,7 +441,7 @@ class LogFormatter {
$entry = $this->entry;
$params = $this->extractParameters();
$params[0] = Message::rawParam( $this->getPerformerElement() );
- $params[1] = $entry->getPerformer()->getName();
+ $params[1] = $this->canView( LogPage::DELETED_USER ) ? $entry->getPerformer()->getName() : '';
$params[2] = Message::rawParam( $this->makePageLink( $entry->getTarget() ) );
// Bad things happens if the numbers are not in correct order
@@ -425,10 +450,83 @@ class LogFormatter {
}
/**
+ * Formats parameters values dependent to their type
+ * @param string $type The type of the value.
+ * Valid are currently:
+ * * - (empty) or plain: The value is returned as-is
+ * * raw: The value will be added to the log message
+ * as raw parameter (e.g. no escaping)
+ * Use this only if there is no other working
+ * type like user-link or title-link
+ * * msg: The value is a message-key, the output is
+ * the message in user language
+ * * msg-content: The value is a message-key, the output
+ * is the message in content language
+ * * user: The value is a user name, e.g. for GENDER
+ * * user-link: The value is a user name, returns a
+ * link for the user
+ * * title: The value is a page title,
+ * returns name of page
+ * * 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
+ * @return string or Message::numParam or Message::rawParam
+ * Formated value
+ * @since 1.21
+ */
+ protected function formatParameterValue( $type, $value ) {
+ $saveLinkFlood = $this->linkFlood;
+
+ switch ( strtolower( trim( $type ) ) ) {
+ case 'raw':
+ $value = Message::rawParam( $value );
+ break;
+ case 'msg':
+ $value = $this->msg( $value )->text();
+ break;
+ case 'msg-content':
+ $value = $this->msg( $value )->inContentLanguage()->text();
+ break;
+ case 'number':
+ $value = Message::numParam( $value );
+ break;
+ case 'user':
+ $user = User::newFromName( $value );
+ $value = $user->getName();
+ break;
+ case 'user-link':
+ $this->setShowUserToolLinks( false );
+
+ $user = User::newFromName( $value );
+ $value = Message::rawParam( $this->makeUserLink( $user ) );
+
+ $this->setShowUserToolLinks( $saveLinkFlood );
+ break;
+ case 'title':
+ $title = Title::newFromText( $value );
+ $value = $title->getPrefixedText();
+ break;
+ case 'title-link':
+ $title = Title::newFromText( $value );
+ $value = Message::rawParam( $this->makePageLink( $title ) );
+ break;
+ case 'plain':
+ // Plain text, nothing to do
+ default:
+ // Catch other types and use the old behavior (return as-is)
+ }
+
+ return $value;
+ }
+
+ /**
* Helper to make a link to the page, taking the plaintext
* value in consideration.
* @param $title Title the page
- * @param $parameters array query parameters
+ * @param array $parameters query parameters
+ * @throws MWException
* @return String
*/
protected function makePageLink( Title $title = null, $parameters = array() ) {
@@ -492,7 +590,7 @@ class LogFormatter {
return $this->msg( $message )->text();
}
- $content = $this->msg( $message )->escaped();
+ $content = $this->msg( $message )->escaped();
$attribs = array( 'class' => 'history-deleted' );
return Html::rawElement( 'span', $attribs, $content );
}
@@ -547,6 +645,16 @@ class LogFormatter {
return array();
}
+ /**
+ * @return Output of getMessageParameters() for testing
+ */
+ public function getMessageParametersForTesting() {
+ // This function was added because getMessageParameters() is
+ // protected and a change from protected to public caused
+ // problems with extensions
+ return $this->getMessageParameters();
+ }
+
}
/**
@@ -607,7 +715,7 @@ class LegacyLogFormatter extends LogFormatter {
$performer = $this->getPerformerElement();
if ( !$this->irctext ) {
- $action = $performer . $this->msg( 'word-separator' )->text() . $action;
+ $action = $performer . $this->msg( 'word-separator' )->text() . $action;
}
return $action;
@@ -667,7 +775,7 @@ class LegacyLogFormatter extends LogFormatter {
return $this->msg( 'parentheses' )->rawParams(
$this->context->getLanguage()->pipeList( $links ) )->escaped();
// Show unmerge link
- } elseif( $type == 'merge' && $subtype == 'merge' ) {
+ } elseif ( $type == 'merge' && $subtype == 'merge' ) {
if ( !$this->context->getUser()->isAllowed( 'mergehistory' ) ) {
return '';
}
@@ -706,305 +814,3 @@ class LegacyLogFormatter extends LogFormatter {
}
}
-/**
- * This class formats move log entries.
- * @since 1.19
- */
-class MoveLogFormatter extends LogFormatter {
- public function getPreloadTitles() {
- $params = $this->extractParameters();
- return array( Title::newFromText( $params[3] ) );
- }
-
- protected function getMessageKey() {
- $key = parent::getMessageKey();
- $params = $this->getMessageParameters();
- if ( isset( $params[4] ) && $params[4] === '1' ) {
- $key .= '-noredirect';
- }
- return $key;
- }
-
- 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 );
- return $params;
- }
-
- public function getActionLinks() {
- if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
- || $this->entry->getSubtype() !== 'move'
- || !$this->context->getUser()->isAllowed( 'move' ) )
- {
- return '';
- }
-
- $params = $this->extractParameters();
- $destTitle = Title::newFromText( $params[3] );
- if ( !$destTitle ) {
- return '';
- }
-
- $revert = Linker::linkKnown(
- SpecialPage::getTitleFor( 'Movepage' ),
- $this->msg( 'revertmove' )->escaped(),
- array(),
- array(
- 'wpOldTitle' => $destTitle->getPrefixedDBkey(),
- 'wpNewTitle' => $this->entry->getTarget()->getPrefixedDBkey(),
- 'wpReason' => $this->msg( 'revertmove' )->inContentLanguage()->text(),
- 'wpMovetalk' => 0
- )
- );
- return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
- }
-}
-
-/**
- * This class formats delete log entries.
- * @since 1.19
- */
-class DeleteLogFormatter extends LogFormatter {
- protected function getMessageKey() {
- $key = parent::getMessageKey();
- if ( in_array( $this->entry->getSubtype(), array( 'event', 'revision' ) ) ) {
- if ( count( $this->getMessageParameters() ) < 5 ) {
- return "$key-legacy";
- }
- }
- return $key;
- }
-
- protected function getMessageParameters() {
- if ( isset( $this->parsedParametersDeleteLog ) ) {
- return $this->parsedParametersDeleteLog;
- }
-
- $params = parent::getMessageParameters();
- $subtype = $this->entry->getSubtype();
- if ( in_array( $subtype, array( 'event', 'revision' ) ) ) {
- if (
- ($subtype === 'event' && count( $params ) === 6 ) ||
- ($subtype === 'revision' && isset( $params[3] ) && $params[3] === 'revision' )
- ) {
- $paramStart = $subtype === 'revision' ? 4 : 3;
-
- $old = $this->parseBitField( $params[$paramStart+1] );
- $new = $this->parseBitField( $params[$paramStart+2] );
- list( $hid, $unhid, $extra ) = RevisionDeleter::getChanges( $new, $old );
- $changes = array();
- foreach ( $hid as $v ) {
- $changes[] = $this->msg( "$v-hid" )->plain();
- }
- foreach ( $unhid as $v ) {
- $changes[] = $this->msg( "$v-unhid" )->plain();
- }
- foreach ( $extra as $v ) {
- $changes[] = $this->msg( $v )->plain();
- }
- $changeText = $this->context->getLanguage()->listToText( $changes );
-
-
- $newParams = array_slice( $params, 0, 3 );
- $newParams[3] = $changeText;
- $count = count( explode( ',', $params[$paramStart] ) );
- $newParams[4] = $this->context->getLanguage()->formatNum( $count );
- return $this->parsedParametersDeleteLog = $newParams;
- } else {
- return $this->parsedParametersDeleteLog = array_slice( $params, 0, 3 );
- }
- }
-
- return $this->parsedParametersDeleteLog = $params;
- }
-
- protected function parseBitField( $string ) {
- // Input is like ofield=2134 or just the number
- if ( strpos( $string, 'field=' ) === 1 ) {
- list( , $field ) = explode( '=', $string );
- return (int) $field;
- } else {
- return (int) $string;
- }
- }
-
- public function getActionLinks() {
- $user = $this->context->getUser();
- if ( !$user->isAllowed( 'deletedhistory' ) || $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) {
- return '';
- }
-
- switch ( $this->entry->getSubtype() ) {
- case 'delete': // Show undelete link
- if( $user->isAllowed( 'undelete' ) ) {
- $message = 'undeletelink';
- } else {
- $message = 'undeleteviewlink';
- }
- $revert = Linker::linkKnown(
- SpecialPage::getTitleFor( 'Undelete' ),
- $this->msg( $message )->escaped(),
- array(),
- array( 'target' => $this->entry->getTarget()->getPrefixedDBkey() )
- );
- return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
-
- case 'revision': // If an edit was hidden from a page give a review link to the history
- $params = $this->extractParameters();
- if ( !isset( $params[3] ) || !isset( $params[4] ) ) {
- return '';
- }
-
- // Different revision types use different URL params...
- $key = $params[3];
- // This is a CSV of the IDs
- $ids = explode( ',', $params[4] );
-
- $links = array();
-
- // If there's only one item, we can show a diff link
- if ( count( $ids ) == 1 ) {
- // Live revision diffs...
- if ( $key == 'oldid' || $key == 'revision' ) {
- $links[] = Linker::linkKnown(
- $this->entry->getTarget(),
- $this->msg( 'diff' )->escaped(),
- array(),
- array(
- 'diff' => intval( $ids[0] ),
- 'unhide' => 1
- )
- );
- // Deleted revision diffs...
- } elseif ( $key == 'artimestamp' || $key == 'archive' ) {
- $links[] = Linker::linkKnown(
- SpecialPage::getTitleFor( 'Undelete' ),
- $this->msg( 'diff' )->escaped(),
- array(),
- array(
- 'target' => $this->entry->getTarget()->getPrefixedDBKey(),
- 'diff' => 'prev',
- 'timestamp' => $ids[0]
- )
- );
- }
- }
-
- // View/modify link...
- $links[] = Linker::linkKnown(
- SpecialPage::getTitleFor( 'Revisiondelete' ),
- $this->msg( 'revdel-restore' )->escaped(),
- array(),
- array(
- 'target' => $this->entry->getTarget()->getPrefixedText(),
- 'type' => $key,
- 'ids' => implode( ',', $ids ),
- )
- );
-
- return $this->msg( 'parentheses' )->rawParams(
- $this->context->getLanguage()->pipeList( $links ) )->escaped();
-
- case 'event': // Hidden log items, give review link
- $params = $this->extractParameters();
- if ( !isset( $params[3] ) ) {
- return '';
- }
- // This is a CSV of the IDs
- $query = $params[3];
- // Link to each hidden object ID, $params[1] is the url param
- $revert = Linker::linkKnown(
- SpecialPage::getTitleFor( 'Revisiondelete' ),
- $this->msg( 'revdel-restore' )->escaped(),
- array(),
- array(
- 'target' => $this->entry->getTarget()->getPrefixedText(),
- 'type' => 'logging',
- 'ids' => $query
- )
- );
- return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
- default:
- return '';
- }
- }
-}
-
-/**
- * This class formats patrol log entries.
- * @since 1.19
- */
-class PatrolLogFormatter extends LogFormatter {
- protected function getMessageKey() {
- $key = parent::getMessageKey();
- $params = $this->getMessageParameters();
- if ( isset( $params[5] ) && $params[5] ) {
- $key .= '-auto';
- }
- return $key;
- }
-
- protected function getMessageParameters() {
- $params = parent::getMessageParameters();
-
- $target = $this->entry->getTarget();
- $oldid = $params[3];
- $revision = $this->context->getLanguage()->formatNum( $oldid, true );
-
- if ( $this->plaintext ) {
- $revlink = $revision;
- } elseif ( $target->exists() ) {
- $query = array(
- 'oldid' => $oldid,
- 'diff' => 'prev'
- );
- $revlink = Linker::link( $target, htmlspecialchars( $revision ), array(), $query );
- } else {
- $revlink = htmlspecialchars( $revision );
- }
-
- $params[3] = Message::rawParam( $revlink );
- return $params;
- }
-}
-
-/**
- * This class formats new user log entries.
- * @since 1.19
- */
-class NewUsersLogFormatter extends LogFormatter {
- protected function getMessageParameters() {
- $params = parent::getMessageParameters();
- if ( $this->entry->getSubtype() === 'create2' ) {
- if ( isset( $params[3] ) ) {
- $target = User::newFromId( $params[3] );
- } else {
- $target = User::newFromName( $this->entry->getTarget()->getText(), false );
- }
- $params[2] = Message::rawParam( $this->makeUserLink( $target ) );
- $params[3] = $target->getName();
- }
- return $params;
- }
-
- public function getComment() {
- $timestamp = wfTimestamp( TS_MW, $this->entry->getTimestamp() );
- if ( $timestamp < '20080129000000' ) {
- # Suppress $comment from old entries (before 2008-01-29),
- # not needed and can contain incorrect links
- return '';
- }
- return parent::getComment();
- }
-
- public function getPreloadTitles() {
- if ( $this->entry->getSubtype() === 'create2' ) {
- //add the user talk to LinkBatch for the userLink
- return array( Title::makeTitle( NS_USER_TALK, $this->entry->getTarget()->getText() ) );
- }
- return array();
- }
-}
diff --git a/includes/logging/LogPage.php b/includes/logging/LogPage.php
index d96a5ea5..cc473c18 100644
--- a/includes/logging/LogPage.php
+++ b/includes/logging/LogPage.php
@@ -50,16 +50,16 @@ class LogPage {
*/
var $target;
- /* @acess public */
+ /* @access public */
var $updateRecentChanges, $sendToUDP;
/**
* Constructor
*
- * @param $type String: one of '', 'block', 'protect', 'rights', 'delete',
+ * @param string $type one of '', 'block', 'protect', 'rights', 'delete',
* 'upload', 'move'
* @param $rc Boolean: whether to update recent changes as well as the logging table
- * @param $udp String: pass 'UDP' to send to the UDP feed if NOT sent to RC
+ * @param string $udp pass 'UDP' to send to the UDP feed if NOT sent to RC
*/
public function __construct( $type, $rc = true, $udp = 'skipUDP' ) {
$this->type = $type;
@@ -94,7 +94,7 @@ class LogPage {
$newId = !is_null( $log_id ) ? $log_id : $dbw->insertId();
# And update recentchanges
- if( $this->updateRecentChanges ) {
+ if ( $this->updateRecentChanges ) {
$titleObj = SpecialPage::getTitleFor( 'Log', $this->type );
RecentChange::notifyLog(
@@ -102,9 +102,9 @@ class LogPage {
$this->type, $this->action, $this->target, $this->comment,
$this->params, $newId, $this->getRcCommentIRC()
);
- } elseif( $this->sendToUDP ) {
+ } elseif ( $this->sendToUDP ) {
# Don't send private logs to UDP
- if( isset( $wgLogRestrictions[$this->type] ) && $wgLogRestrictions[$this->type] != '*' ) {
+ if ( isset( $wgLogRestrictions[$this->type] ) && $wgLogRestrictions[$this->type] != '*' ) {
return $newId;
}
@@ -129,7 +129,7 @@ class LogPage {
public function getRcComment() {
$rcComment = $this->actionText;
- if( $this->comment != '' ) {
+ if ( $this->comment != '' ) {
if ( $rcComment == '' ) {
$rcComment = $this->comment;
} else {
@@ -149,7 +149,7 @@ class LogPage {
public function getRcCommentIRC() {
$rcComment = $this->ircActionText;
- if( $this->comment != '' ) {
+ if ( $this->comment != '' ) {
if ( $rcComment == '' ) {
$rcComment = $this->comment;
} else {
@@ -181,7 +181,7 @@ class LogPage {
/**
* Is $type a valid log type
*
- * @param $type String: log type to check
+ * @param string $type log type to check
* @return Boolean
*/
public static function isLogType( $type ) {
@@ -191,14 +191,14 @@ class LogPage {
/**
* Get the name for the given log type
*
- * @param $type String: logtype
+ * @param string $type logtype
* @return String: log name
* @deprecated in 1.19, warnings in 1.21. Use getName()
*/
public static function logName( $type ) {
global $wgLogNames;
- if( isset( $wgLogNames[$type] ) ) {
+ if ( isset( $wgLogNames[$type] ) ) {
return str_replace( '_', ' ', wfMessage( $wgLogNames[$type] )->text() );
} else {
// Bogus log types? Perhaps an extension was removed.
@@ -210,7 +210,7 @@ class LogPage {
* Get the log header for the given log type
*
* @todo handle missing log types
- * @param $type String: logtype
+ * @param string $type logtype
* @return String: headertext of this logtype
* @deprecated in 1.19, warnings in 1.21. Use getDescription()
*/
@@ -220,15 +220,15 @@ class LogPage {
}
/**
- * Generate text for a log entry.
+ * Generate text for a log entry.
* Only LogFormatter should call this function.
*
- * @param $type String: log type
- * @param $action String: log action
+ * @param string $type log type
+ * @param string $action log action
* @param $title Mixed: Title object or null
* @param $skin Mixed: Skin object or null. If null, we want to use the wiki
* content language, since that will go to the IRC feed.
- * @param $params Array: parameters
+ * @param array $params parameters
* @param $filterWikilinks Boolean: whether to filter wiki links
* @return HTML string
*/
@@ -247,36 +247,13 @@ class LogPage {
$key = "$type/$action";
- if( isset( $wgLogActions[$key] ) ) {
- if( is_null( $title ) ) {
+ if ( isset( $wgLogActions[$key] ) ) {
+ if ( is_null( $title ) ) {
$rv = wfMessage( $wgLogActions[$key] )->inLanguage( $langObj )->escaped();
} else {
$titleLink = self::getTitleLink( $type, $langObjOrNull, $title, $params );
- if( preg_match( '/^rights\/(rights|autopromote)/', $key ) ) {
- $rightsnone = wfMessage( 'rightsnone' )->inLanguage( $langObj )->text();
-
- if( $skin ) {
- $username = $title->getText();
- foreach ( $params as &$param ) {
- $groupArray = array_map( 'trim', explode( ',', $param ) );
- foreach( $groupArray as &$group ) {
- $group = User::getGroupMember( $group, $username );
- }
- $param = $wgLang->listToText( $groupArray );
- }
- }
-
- if( !isset( $params[0] ) || trim( $params[0] ) == '' ) {
- $params[0] = $rightsnone;
- }
-
- if( !isset( $params[1] ) || trim( $params[1] ) == '' ) {
- $params[1] = $rightsnone;
- }
- }
-
- if( count( $params ) == 0 ) {
+ if ( count( $params ) == 0 ) {
$rv = wfMessage( $wgLogActions[$key] )->rawParams( $titleLink )->inLanguage( $langObj )->escaped();
} else {
$details = '';
@@ -285,7 +262,7 @@ class LogPage {
// User suppression
if ( preg_match( '/^(block|suppress)\/(block|reblock)$/', $key ) ) {
if ( $skin ) {
- $params[1] = '<span class="blockExpiry" dir="ltr" title="' . htmlspecialchars( $params[1] ). '">' .
+ $params[1] = '<span class="blockExpiry" title="&lrm;' . htmlspecialchars( $params[1] ) . '">' .
$wgLang->translateBlockExpiry( $params[1] ) . '</span>';
} else {
$params[1] = $wgContLang->translateBlockExpiry( $params[1] );
@@ -294,16 +271,16 @@ class LogPage {
$params[2] = isset( $params[2] ) ?
self::formatBlockFlags( $params[2], $langObj ) : '';
// Page protections
- } elseif ( $type == 'protect' && count($params) == 3 ) {
+ } elseif ( $type == 'protect' && count( $params ) == 3 ) {
// Restrictions and expiries
- if( $skin ) {
+ if ( $skin ) {
$details .= $wgLang->getDirMark() . htmlspecialchars( " {$params[1]}" );
} else {
$details .= " {$params[1]}";
}
// Cascading flag...
- if( $params[2] ) {
+ if ( $params[2] ) {
$details .= ' [' . wfMessage( 'protect-summary-cascade' )->inLanguage( $langObj )->text() . ']';
}
}
@@ -314,7 +291,7 @@ class LogPage {
} else {
global $wgLogActionsHandlers;
- if( isset( $wgLogActionsHandlers[$key] ) ) {
+ if ( isset( $wgLogActionsHandlers[$key] ) ) {
$args = func_get_args();
$rv = call_user_func_array( $wgLogActionsHandlers[$key], $args );
} else {
@@ -333,7 +310,7 @@ class LogPage {
// you want to link to something OTHER than the title of the log entry.
// The real problem, which Erik was trying to fix (and it sort-of works now) is
// that the same messages are being treated as both wikitext *and* HTML.
- if( $filterWikilinks ) {
+ if ( $filterWikilinks ) {
$rv = str_replace( '[[', '', $rv );
$rv = str_replace( ']]', '', $rv );
}
@@ -350,13 +327,11 @@ class LogPage {
* @return String
*/
protected static function getTitleLink( $type, $lang, $title, &$params ) {
- global $wgContLang, $wgUserrightsInterwikiDelimiter;
-
- if( !$lang ) {
+ if ( !$lang ) {
return $title->getPrefixedText();
}
- switch( $type ) {
+ switch ( $type ) {
case 'move':
$titleLink = Linker::link(
$title,
@@ -378,7 +353,7 @@ class LogPage {
}
break;
case 'block':
- if( substr( $title->getText(), 0, 1 ) == '#' ) {
+ if ( substr( $title->getText(), 0, 1 ) == '#' ) {
$titleLink = $title->getText();
} else {
// @todo Store the user identifier in the parameters
@@ -388,20 +363,6 @@ class LogPage {
. Linker::userToolLinks( $id, $title->getText(), false, Linker::TOOL_LINKS_NOBLOCK );
}
break;
- case 'rights':
- $text = $wgContLang->ucfirst( $title->getText() );
- $parts = explode( $wgUserrightsInterwikiDelimiter, $text, 2 );
-
- if ( count( $parts ) == 2 ) {
- $titleLink = WikiMap::foreignUserLink( $parts[1], $parts[0],
- htmlspecialchars( $title->getPrefixedText() ) );
-
- if ( $titleLink !== false ) {
- break;
- }
- }
- $titleLink = Linker::link( Title::makeTitle( NS_USER, $text ) );
- break;
case 'merge':
$titleLink = Linker::link(
$title,
@@ -416,11 +377,11 @@ class LogPage {
$params[1] = $lang->timeanddate( $params[1] );
break;
default:
- if( $title->isSpecialPage() ) {
+ if ( $title->isSpecialPage() ) {
list( $name, $par ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
# Use the language name for log titles, rather than Log/X
- if( $name == 'Log' ) {
+ if ( $name == 'Log' ) {
$logPage = new LogPage( $par );
$titleLink = Linker::link( $title, $logPage->getName()->escaped() );
$titleLink = wfMessage( 'parentheses' )
@@ -441,10 +402,10 @@ class LogPage {
/**
* Add a log entry
*
- * @param $action String: one of '', 'block', 'protect', 'rights', 'delete', 'upload', 'move', 'move_redir'
+ * @param string $action one of '', 'block', 'protect', 'rights', 'delete', 'upload', 'move', 'move_redir'
* @param $target Title object
- * @param $comment String: description associated
- * @param $params Array: parameters passed later to wfMessage function
+ * @param string $comment description associated
+ * @param array $params parameters passed later to wfMessage function
* @param $doer User object: the user doing the action
*
* @return int log_id of the inserted log entry
@@ -460,6 +421,9 @@ class LogPage {
$comment = '';
}
+ # Trim spaces on user supplied text
+ $comment = trim( $comment );
+
# Truncate for whole multibyte characters.
$comment = $wgContLang->truncate( $comment, 255 );
@@ -501,13 +465,13 @@ class LogPage {
* @return Boolean
*/
public function addRelations( $field, $values, $logid ) {
- if( !strlen( $field ) || empty( $values ) ) {
+ if ( !strlen( $field ) || empty( $values ) ) {
return false; // nothing
}
$data = array();
- foreach( $values as $value ) {
+ foreach ( $values as $value ) {
$data[] = array(
'ls_field' => $field,
'ls_value' => $value,
@@ -549,35 +513,35 @@ class LogPage {
* Convert a comma-delimited list of block log flags
* into a more readable (and translated) form
*
- * @param $flags string Flags to format
+ * @param string $flags Flags to format
* @param $lang Language object to use
* @return String
*/
public static function formatBlockFlags( $flags, $lang ) {
- $flags = explode( ',', trim( $flags ) );
+ $flags = trim( $flags );
+ if ( $flags === '' ) {
+ return ''; //nothing to do
+ }
+ $flags = explode( ',', $flags );
- if( count( $flags ) > 0 ) {
- for( $i = 0; $i < count( $flags ); $i++ ) {
- $flags[$i] = self::formatBlockFlag( $flags[$i], $lang );
- }
- return wfMessage( 'parentheses' )->inLanguage( $lang )
- ->rawParams( $lang->commaList( $flags ) )->escaped();
- } else {
- return '';
+ for ( $i = 0; $i < count( $flags ); $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 $flag int Flag to translate
+ * @param int $flag Flag to translate
* @param $lang Language object to use
* @return String
*/
public static function formatBlockFlag( $flag, $lang ) {
static $messages = array();
- if( !isset( $messages[$flag] ) ) {
+ if ( !isset( $messages[$flag] ) ) {
$messages[$flag] = htmlspecialchars( $flag ); // Fallback
// For grepping. The following core messages can be used here:
@@ -598,7 +562,6 @@ class LogPage {
return $messages[$flag];
}
-
/**
* Name of the log.
* @return Message
diff --git a/includes/logging/LogPager.php b/includes/logging/LogPager.php
index ea1be8e0..09ae3b8c 100644
--- a/includes/logging/LogPager.php
+++ b/includes/logging/LogPager.php
@@ -34,15 +34,15 @@ class LogPager extends ReverseChronologicalPager {
/**
* Constructor
*
- * @param $list LogEventsList
- * @param $types String or Array: log types to show
- * @param $performer String: the user who made the log entries
- * @param $title String|Title: the page title the log entries are for
- * @param $pattern String: do a prefix search rather than an exact title match
- * @param $conds Array: extra conditions for the query
- * @param $year Integer: the year to start from
- * @param $month Integer: the month to start from
- * @param $tagFilter String: tag
+ * @param LogEventsList $list
+ * @param string $types or Array: log types to show
+ * @param string $performer the user who made the log entries
+ * @param string|Title $title the page title the log entries are for
+ * @param string $pattern do a prefix search rather than an exact title match
+ * @param array $conds extra conditions for the query
+ * @param int $year The year to start from
+ * @param int $month The month to start from
+ * @param string $tagFilter tag
*/
public function __construct( $list, $types = array(), $performer = '', $title = '', $pattern = '',
$conds = array(), $year = false, $month = false, $tagFilter = '' ) {
@@ -71,16 +71,17 @@ class LogPager extends ReverseChronologicalPager {
public function getFilterParams() {
global $wgFilterLogTypes;
$filters = array();
- if( count($this->types) ) {
+ if ( count( $this->types ) ) {
return $filters;
}
- foreach( $wgFilterLogTypes as $type => $default ) {
+ foreach ( $wgFilterLogTypes as $type => $default ) {
// Avoid silly filtering
- if( $type !== 'patrol' || $this->getUser()->useNPPatrol() ) {
+ if ( $type !== 'patrol' || $this->getUser()->useNPPatrol() ) {
$hide = $this->getRequest()->getInt( "hide_{$type}_log", $default );
$filters[$type] = $hide;
- if( $hide )
+ if ( $hide ) {
$this->mConds[] = 'log_type != ' . $this->mDb->addQuotes( $type );
+ }
}
}
return $filters;
@@ -90,18 +91,20 @@ class LogPager extends ReverseChronologicalPager {
* Set the log reader to return only entries of the given type.
* Type restrictions enforced here
*
- * @param $types String or array: Log types ('upload', 'delete', etc);
+ * @param string $types or array: Log types ('upload', 'delete', etc);
* empty string means no restriction
*/
private function limitType( $types ) {
global $wgLogRestrictions;
+
+ $user = $this->getUser();
// If $types is not an array, make it an array
- $types = ($types === '') ? array() : (array)$types;
+ $types = ( $types === '' ) ? array() : (array)$types;
// Don't even show header for private logs; don't recognize it...
$needReindex = false;
foreach ( $types as $type ) {
- if( isset( $wgLogRestrictions[$type] )
- && !$this->getUser()->isAllowed($wgLogRestrictions[$type])
+ if ( isset( $wgLogRestrictions[$type] )
+ && !$user->isAllowed( $wgLogRestrictions[$type] )
) {
$needReindex = true;
$types = array_diff( $types, array( $type ) );
@@ -116,34 +119,36 @@ class LogPager extends ReverseChronologicalPager {
// Don't show private logs to unprivileged users.
// Also, only show them upon specific request to avoid suprises.
$audience = $types ? 'user' : 'public';
- $hideLogs = LogEventsList::getExcludeClause( $this->mDb, $audience );
- if( $hideLogs !== false ) {
+ $hideLogs = LogEventsList::getExcludeClause( $this->mDb, $audience, $user );
+ if ( $hideLogs !== false ) {
$this->mConds[] = $hideLogs;
}
- if( count($types) ) {
+ if ( count( $types ) ) {
$this->mConds['log_type'] = $types;
// Set typeCGI; used in url param for paging
- if( count($types) == 1 ) $this->typeCGI = $types[0];
+ if ( count( $types ) == 1 ) {
+ $this->typeCGI = $types[0];
+ }
}
}
/**
* Set the log reader to return only entries by the given user.
*
- * @param $name String: (In)valid user name
+ * @param string $name (In)valid user name
* @return bool
*/
private function limitPerformer( $name ) {
- if( $name == '' ) {
+ if ( $name == '' ) {
return false;
}
$usertitle = Title::makeTitleSafe( NS_USER, $name );
- if( is_null($usertitle) ) {
+ if ( is_null( $usertitle ) ) {
return false;
}
/* Fetch userid at first, if known, provides awesome query plan afterwards */
$userid = User::idFromName( $name );
- if( !$userid ) {
+ if ( !$userid ) {
/* It should be nicer to abort query at all,
but for now it won't pass anywhere behind the optimizer */
$this->mConds[] = "NULL";
@@ -151,10 +156,10 @@ class LogPager extends ReverseChronologicalPager {
$this->mConds['log_user'] = $userid;
// Paranoia: avoid brute force searches (bug 17342)
$user = $this->getUser();
- if( !$user->isAllowed( 'deletedhistory' ) ) {
- $this->mConds[] = $this->mDb->bitAnd('log_deleted', LogPage::DELETED_USER) . ' = 0';
- } elseif( !$user->isAllowed( 'suppressrevision' ) ) {
- $this->mConds[] = $this->mDb->bitAnd('log_deleted', LogPage::SUPPRESSED_USER) .
+ if ( !$user->isAllowed( 'deletedhistory' ) ) {
+ $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::DELETED_USER ) . ' = 0';
+ } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+ $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_USER ) .
' != ' . LogPage::SUPPRESSED_USER;
}
$this->performer = $usertitle->getText();
@@ -165,7 +170,7 @@ class LogPager extends ReverseChronologicalPager {
* Set the log reader to return only entries affecting the given page.
* (For the block and rights logs, this is a user page.)
*
- * @param $page String or Title object: Title name
+ * @param string $page or Title object: Title name
* @param $pattern String
* @return bool
*/
@@ -176,7 +181,7 @@ class LogPager extends ReverseChronologicalPager {
$title = $page;
} else {
$title = Title::newFromText( $page );
- if( strlen( $page ) == 0 || !$title instanceof Title ) {
+ if ( strlen( $page ) == 0 || !$title instanceof Title ) {
return false;
}
}
@@ -196,7 +201,7 @@ class LogPager extends ReverseChronologicalPager {
# use the page_time index. That should have no more than a few hundred
# log entries for even the busiest pages, so it can be safely scanned
# in full to satisfy an impossible condition on user or similar.
- if( $pattern && !$wgMiserMode ) {
+ if ( $pattern && !$wgMiserMode ) {
$this->mConds['log_namespace'] = $ns;
$this->mConds[] = 'log_title ' . $db->buildLike( $title->getDBkey(), $db->anyString() );
$this->pattern = $pattern;
@@ -206,10 +211,10 @@ class LogPager extends ReverseChronologicalPager {
}
// Paranoia: avoid brute force searches (bug 17342)
$user = $this->getUser();
- if( !$user->isAllowed( 'deletedhistory' ) ) {
- $this->mConds[] = $db->bitAnd('log_deleted', LogPage::DELETED_ACTION) . ' = 0';
- } elseif( !$user->isAllowed( 'suppressrevision' ) ) {
- $this->mConds[] = $db->bitAnd('log_deleted', LogPage::SUPPRESSED_ACTION) .
+ if ( !$user->isAllowed( 'deletedhistory' ) ) {
+ $this->mConds[] = $db->bitAnd( 'log_deleted', LogPage::DELETED_ACTION ) . ' = 0';
+ } elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
+ $this->mConds[] = $db->bitAnd( 'log_deleted', LogPage::SUPPRESSED_ACTION ) .
' != ' . LogPage::SUPPRESSED_ACTION;
}
}
@@ -232,7 +237,7 @@ class LogPager extends ReverseChronologicalPager {
# Add log_search table if there are conditions on it.
# This filters the results to only include log rows that have
# log_search records with the specified ls_field and ls_value values.
- if( array_key_exists( 'ls_field', $this->mConds ) ) {
+ if ( array_key_exists( 'ls_field', $this->mConds ) ) {
$tables[] = 'log_search';
$index['log_search'] = 'ls_field_val';
$index['logging'] = 'PRIMARY';
@@ -244,28 +249,18 @@ class LogPager extends ReverseChronologicalPager {
# no duplicate log rows. Otherwise, we need to remove the duplicates.
$options[] = 'DISTINCT';
}
- # Avoid usage of the wrong index by limiting
- # the choices of available indexes. This mainly
- # avoids site-breaking filesorts.
- } elseif( $this->title || $this->pattern || $this->performer ) {
- $index['logging'] = array( 'page_time', 'user_time' );
- if( count($this->types) == 1 ) {
- $index['logging'][] = 'log_user_type_time';
- }
- } elseif( count($this->types) == 1 ) {
- $index['logging'] = 'type_time';
- } else {
- $index['logging'] = 'times';
}
- $options['USE INDEX'] = $index;
+ if ( count( $index ) ) {
+ $options['USE INDEX'] = $index;
+ }
# Don't show duplicate rows when using log_search
$joins['log_search'] = array( 'INNER JOIN', 'ls_log_id=log_id' );
$info = array(
- 'tables' => $tables,
- 'fields' => $fields,
- 'conds' => array_merge( $conds, $this->mConds ),
- 'options' => $options,
+ 'tables' => $tables,
+ 'fields' => $fields,
+ 'conds' => array_merge( $conds, $this->mConds ),
+ 'options' => $options,
'join_conds' => $joins,
);
# Add ChangeTags filter query
@@ -293,7 +288,7 @@ class LogPager extends ReverseChronologicalPager {
public function getStartBody() {
wfProfileIn( __METHOD__ );
# Do a link batch query
- if( $this->getNumRows() > 0 ) {
+ if ( $this->getNumRows() > 0 ) {
$lb = new LinkBatch;
foreach ( $this->mResult as $row ) {
$lb->add( $row->log_namespace, $row->log_title );
diff --git a/includes/logging/MoveLogFormatter.php b/includes/logging/MoveLogFormatter.php
new file mode 100644
index 00000000..0978f976
--- /dev/null
+++ b/includes/logging/MoveLogFormatter.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Formatter for move 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
+ * @author Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ * @since 1.22
+ */
+
+/**
+ * This class formats move log entries.
+ *
+ * @since 1.19
+ */
+class MoveLogFormatter extends LogFormatter {
+ public function getPreloadTitles() {
+ $params = $this->extractParameters();
+ return array( Title::newFromText( $params[3] ) );
+ }
+
+ protected function getMessageKey() {
+ $key = parent::getMessageKey();
+ $params = $this->getMessageParameters();
+ if ( isset( $params[4] ) && $params[4] === '1' ) {
+ $key .= '-noredirect';
+ }
+ return $key;
+ }
+
+ 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 );
+ return $params;
+ }
+
+ public function getActionLinks() {
+ if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
+ || $this->entry->getSubtype() !== 'move'
+ || !$this->context->getUser()->isAllowed( 'move' ) )
+ {
+ return '';
+ }
+
+ $params = $this->extractParameters();
+ $destTitle = Title::newFromText( $params[3] );
+ if ( !$destTitle ) {
+ return '';
+ }
+
+ $revert = Linker::linkKnown(
+ SpecialPage::getTitleFor( 'Movepage' ),
+ $this->msg( 'revertmove' )->escaped(),
+ array(),
+ array(
+ 'wpOldTitle' => $destTitle->getPrefixedDBkey(),
+ 'wpNewTitle' => $this->entry->getTarget()->getPrefixedDBkey(),
+ 'wpReason' => $this->msg( 'revertmove' )->inContentLanguage()->text(),
+ 'wpMovetalk' => 0
+ )
+ );
+ return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
+ }
+}
diff --git a/includes/logging/NewUsersLogFormatter.php b/includes/logging/NewUsersLogFormatter.php
new file mode 100644
index 00000000..602728b4
--- /dev/null
+++ b/includes/logging/NewUsersLogFormatter.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ * Formatter for new user 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
+ * @author Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ * @since 1.22
+ */
+
+/**
+ * This class formats new user log entries.
+ *
+ * @since 1.19
+ */
+class NewUsersLogFormatter extends LogFormatter {
+ protected function getMessageParameters() {
+ $params = parent::getMessageParameters();
+ $subtype = $this->entry->getSubtype();
+ if ( $subtype === 'create2' || $subtype === 'byemail' ) {
+ if ( isset( $params[3] ) ) {
+ $target = User::newFromId( $params[3] );
+ } else {
+ $target = User::newFromName( $this->entry->getTarget()->getText(), false );
+ }
+ $params[2] = Message::rawParam( $this->makeUserLink( $target ) );
+ $params[3] = $target->getName();
+ }
+ return $params;
+ }
+
+ public function getComment() {
+ $timestamp = wfTimestamp( TS_MW, $this->entry->getTimestamp() );
+ if ( $timestamp < '20080129000000' ) {
+ # Suppress $comment from old entries (before 2008-01-29),
+ # not needed and can contain incorrect links
+ return '';
+ }
+ return parent::getComment();
+ }
+
+ public function getPreloadTitles() {
+ $subtype = $this->entry->getSubtype();
+ if ( $subtype === 'create2' || $subtype === 'byemail' ) {
+ //add the user talk to LinkBatch for the userLink
+ return array( Title::makeTitle( NS_USER_TALK, $this->entry->getTarget()->getText() ) );
+ }
+ return array();
+ }
+}
diff --git a/includes/logging/PatrolLog.php b/includes/logging/PatrolLog.php
index 911fffc0..bb76d5a9 100644
--- a/includes/logging/PatrolLog.php
+++ b/includes/logging/PatrolLog.php
@@ -38,6 +38,13 @@ class PatrolLog {
* @return bool
*/
public static function record( $rc, $auto = false, User $user = null ) {
+ global $wgLogAutopatrol;
+
+ // do not log autopatrolled edits if setting disables it
+ if ( $auto && !$wgLogAutopatrol ) {
+ return false;
+ }
+
if ( !$rc instanceof RecentChange ) {
$rc = RecentChange::newFromId( $rc );
if ( !is_object( $rc ) ) {
diff --git a/includes/logging/PatrolLogFormatter.php b/includes/logging/PatrolLogFormatter.php
new file mode 100644
index 00000000..507039ba
--- /dev/null
+++ b/includes/logging/PatrolLogFormatter.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Formatter for new user 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
+ * @author Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ * @since 1.22
+ */
+
+/**
+ * This class formats patrol log entries.
+ *
+ * @since 1.19
+ */
+class PatrolLogFormatter extends LogFormatter {
+ protected function getMessageKey() {
+ $key = parent::getMessageKey();
+ $params = $this->getMessageParameters();
+ if ( isset( $params[5] ) && $params[5] ) {
+ $key .= '-auto';
+ }
+ return $key;
+ }
+
+ protected function getMessageParameters() {
+ $params = parent::getMessageParameters();
+
+ $target = $this->entry->getTarget();
+ $oldid = $params[3];
+ $revision = $this->context->getLanguage()->formatNum( $oldid, true );
+
+ if ( $this->plaintext ) {
+ $revlink = $revision;
+ } elseif ( $target->exists() ) {
+ $query = array(
+ 'oldid' => $oldid,
+ 'diff' => 'prev'
+ );
+ $revlink = Linker::link( $target, htmlspecialchars( $revision ), array(), $query );
+ } else {
+ $revlink = htmlspecialchars( $revision );
+ }
+
+ $params[3] = Message::rawParam( $revlink );
+ return $params;
+ }
+}
diff --git a/includes/logging/RightsLogFormatter.php b/includes/logging/RightsLogFormatter.php
new file mode 100644
index 00000000..d3daf6ee
--- /dev/null
+++ b/includes/logging/RightsLogFormatter.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Formatter for user rights 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
+ * @author Alexandre Emsenhuber
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ * @since 1.22
+ */
+
+/**
+ * This class formats rights log entries.
+ *
+ * @since 1.21
+ */
+class RightsLogFormatter extends LogFormatter {
+ protected function makePageLink( Title $title = null, $parameters = array() ) {
+ global $wgContLang, $wgUserrightsInterwikiDelimiter;
+
+ if ( !$this->plaintext ) {
+ $text = $wgContLang->ucfirst( $title->getText() );
+ $parts = explode( $wgUserrightsInterwikiDelimiter, $text, 2 );
+
+ if ( count( $parts ) === 2 ) {
+ $titleLink = WikiMap::foreignUserLink( $parts[1], $parts[0],
+ htmlspecialchars( $title->getPrefixedText() ) );
+
+ if ( $titleLink !== false ) {
+ return $titleLink;
+ }
+ }
+ }
+
+ return parent::makePageLink( $title, $parameters );
+ }
+
+ protected function getMessageKey() {
+ $key = parent::getMessageKey();
+ $params = $this->getMessageParameters();
+ if ( !isset( $params[3] ) && !isset( $params[4] ) ) {
+ $key .= '-legacy';
+ }
+ return $key;
+ }
+
+ protected function getMessageParameters() {
+ $params = parent::getMessageParameters();
+
+ // Really old entries
+ if ( !isset( $params[3] ) && !isset( $params[4] ) ) {
+ 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 ) );
+ }
+
+ $userName = $this->entry->getTarget()->getText();
+ if ( !$this->plaintext && count( $oldGroups ) ) {
+ foreach ( $oldGroups as &$group ) {
+ $group = User::getGroupMember( $group, $userName );
+ }
+ }
+ if ( !$this->plaintext && count( $newGroups ) ) {
+ foreach ( $newGroups as &$group ) {
+ $group = User::getGroupMember( $group, $userName );
+ }
+ }
+
+ $lang = $this->context->getLanguage();
+ if ( count( $oldGroups ) ) {
+ $params[3] = $lang->listToText( $oldGroups );
+ } else {
+ $params[3] = $this->msg( 'rightsnone' )->text();
+ }
+ if ( count( $newGroups ) ) {
+ // Array_values is used here because of bug 42211
+ // see use of array_unique in UserrightsPage::doSaveUserGroups on $newGroups.
+ $params[4] = $lang->listToText( array_values( $newGroups ) );
+ } else {
+ $params[4] = $this->msg( 'rightsnone' )->text();
+ }
+
+ return $params;
+ }
+}