summaryrefslogtreecommitdiff
path: root/includes/logging
diff options
context:
space:
mode:
Diffstat (limited to 'includes/logging')
-rw-r--r--includes/logging/LogEntry.php78
-rw-r--r--includes/logging/LogEventsList.php84
-rw-r--r--includes/logging/LogFormatter.php234
-rw-r--r--includes/logging/LogPage.php75
-rw-r--r--includes/logging/LogPager.php44
5 files changed, 347 insertions, 168 deletions
diff --git a/includes/logging/LogEntry.php b/includes/logging/LogEntry.php
index 37560d80..0f20ed16 100644
--- a/includes/logging/LogEntry.php
+++ b/includes/logging/LogEntry.php
@@ -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() {
@@ -335,9 +342,9 @@ class ManualLogEntry extends LogEntryBase {
/**
* Constructor.
- *
+ *
* @since 1.19
- *
+ *
* @param string $type
* @param string $subtype
*/
@@ -357,10 +364,10 @@ 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;
@@ -368,9 +375,9 @@ class ManualLogEntry extends LogEntryBase {
/**
* Set the user that performed the action being logged.
- *
+ *
* @since 1.19
- *
+ *
* @param User $performer
*/
public function setPerformer( User $performer ) {
@@ -379,9 +386,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 +397,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 +408,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 +419,9 @@ class ManualLogEntry extends LogEntryBase {
/**
* TODO: document
- *
+ *
* @since 1.19
- *
+ *
* @param integer $deleted
*/
public function setDeleted( $deleted ) {
@@ -435,8 +442,11 @@ class ManualLogEntry extends LogEntryBase {
$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,
@@ -458,8 +468,8 @@ class ManualLogEntry extends LogEntryBase {
/**
* 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() );
diff --git a/includes/logging/LogEventsList.php b/includes/logging/LogEventsList.php
index 4de1a974..501af7d6 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,7 +74,7 @@ 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 ) ) {
$page = new LogPage( $headerType );
@@ -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,8 +97,8 @@ 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' );
@@ -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( ' ', $tagSelector ) );
}
// Filter links
- if ($filter) {
+ if ( $filter ) {
$html .= Xml::tags( 'p', null, $this->getFilterLinks( $filter ) );
}
@@ -162,7 +162,7 @@ class LogEventsList extends ContextSource {
$query = $this->getDefaultQuery();
$queryKey = "hide_{$type}_log";
- $hideVal = 1 - intval($val);
+ $hideVal = 1 - intval( $val );
$query[$queryKey] = $hideVal;
$link = Linker::linkKnown(
@@ -176,7 +176,7 @@ class LogEventsList extends ContextSource {
$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 +198,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 +212,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 +221,7 @@ class LogEventsList extends ContextSource {
}
// Second pass to sort by name
- asort($typesByName);
+ asort( $typesByName );
// Always put "All public logs" on top
$public = $typesByName[''];
@@ -273,10 +273,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 +307,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() ) );
@@ -351,9 +350,9 @@ class LogEventsList extends ContextSource {
$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.
+ $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 {
@@ -383,8 +382,8 @@ 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 ) {
$match = is_array( $action ) ?
@@ -450,10 +449,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
@@ -468,13 +467,13 @@ class LogEventsList extends ContextSource {
* @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
);
@@ -520,8 +519,8 @@ class LogEventsList extends ContextSource {
}
}
$s .= $loglist->beginLogEventsList() .
- $logBody .
- $loglist->endLogEventsList();
+ $logBody .
+ $loglist->endLogEventsList();
} else {
if ( $showIfEmpty ) {
$s = Html::rawElement( 'div', array( 'class' => 'mw-warning-logempty' ),
@@ -535,7 +534,7 @@ class LogEventsList extends ContextSource {
} elseif ( $page != '' ) {
$urlParam['page'] = $page;
}
- if ( $user != '')
+ if ( $user != '' )
$urlParam['user'] = $user;
if ( !is_array( $types ) ) # Make it an array, if it isn't
$types = array( $types );
@@ -560,7 +559,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 +574,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;
+ 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) . ')';
+ return 'log_type NOT IN (' . $db->makeList( $hiddenLogs ) . ')';
}
return false;
}
- }
+}
diff --git a/includes/logging/LogFormatter.php b/includes/logging/LogFormatter.php
index 7586bb65..ace26bbe 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() ) {
case 'move':
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;
@@ -270,6 +270,7 @@ class LogFormatter {
->inContentLanguage()->escaped();
break;
case 'create2':
+ case 'byemail':
$text = wfMessage( 'newuserlog-create2-entry' )
->rawParams( $target )->inContentLanguage()->escaped();
break;
@@ -293,6 +294,28 @@ 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:
@@ -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;
@@ -786,9 +894,11 @@ class DeleteLogFormatter extends LogFormatter {
$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' )
+ ( $subtype === 'event' && count( $params ) === 6 ) ||
+ ( $subtype === 'revision' && isset( $params[3] ) && ( $params[3] === 'revision' || $params[3] === 'oldimage' ) )
) {
$paramStart = $subtype === 'revision' ? 4 : 3;
@@ -805,8 +915,7 @@ class DeleteLogFormatter extends LogFormatter {
foreach ( $extra as $v ) {
$changes[] = $this->msg( $v )->plain();
}
- $changeText = $this->context->getLanguage()->listToText( $changes );
-
+ $changeText = $this->context->getLanguage()->listToText( $changes );
$newParams = array_slice( $params, 0, 3 );
$newParams[3] = $changeText;
@@ -849,7 +958,7 @@ class DeleteLogFormatter extends LogFormatter {
$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
@@ -885,7 +994,7 @@ class DeleteLogFormatter extends LogFormatter {
$this->msg( 'diff' )->escaped(),
array(),
array(
- 'target' => $this->entry->getTarget()->getPrefixedDBKey(),
+ 'target' => $this->entry->getTarget()->getPrefixedDBkey(),
'diff' => 'prev',
'timestamp' => $ids[0]
)
@@ -978,7 +1087,8 @@ class PatrolLogFormatter extends LogFormatter {
class NewUsersLogFormatter extends LogFormatter {
protected function getMessageParameters() {
$params = parent::getMessageParameters();
- if ( $this->entry->getSubtype() === 'create2' ) {
+ $subtype = $this->entry->getSubtype();
+ if ( $subtype === 'create2' || $subtype === 'byemail' ) {
if ( isset( $params[3] ) ) {
$target = User::newFromId( $params[3] );
} else {
@@ -1001,10 +1111,98 @@ class NewUsersLogFormatter extends LogFormatter {
}
public function getPreloadTitles() {
- if ( $this->entry->getSubtype() === 'create2' ) {
+ $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();
}
}
+
+/**
+ * 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;
+ }
+}
diff --git a/includes/logging/LogPage.php b/includes/logging/LogPage.php
index d96a5ea5..4191c577 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;
@@ -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,7 +191,7 @@ 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()
*/
@@ -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
*/
@@ -253,29 +253,6 @@ class LogPage {
} 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 ) {
$rv = wfMessage( $wgLogActions[$key] )->rawParams( $titleLink )->inLanguage( $langObj )->escaped();
} else {
@@ -294,7 +271,7 @@ 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 ) {
$details .= $wgLang->getDirMark() . htmlspecialchars( " {$params[1]}" );
@@ -350,8 +327,6 @@ class LogPage {
* @return String
*/
protected static function getTitleLink( $type, $lang, $title, &$params ) {
- global $wgContLang, $wgUserrightsInterwikiDelimiter;
-
if( !$lang ) {
return $title->getPrefixedText();
}
@@ -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,
@@ -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 );
@@ -549,7 +513,7 @@ 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
*/
@@ -570,7 +534,7 @@ class LogPage {
/**
* 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
*/
@@ -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..908755ed 100644
--- a/includes/logging/LogPager.php
+++ b/includes/logging/LogPager.php
@@ -35,14 +35,14 @@ 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 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 $year Integer: the year to start from
* @param $month Integer: the month to start from
- * @param $tagFilter String: tag
+ * @param string $tagFilter tag
*/
public function __construct( $list, $types = array(), $performer = '', $title = '', $pattern = '',
$conds = array(), $year = false, $month = false, $tagFilter = '' ) {
@@ -71,7 +71,7 @@ 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 ) {
@@ -90,18 +90,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;
// 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])
+ && !$user->isAllowed( $wgLogRestrictions[$type] )
) {
$needReindex = true;
$types = array_diff( $types, array( $type ) );
@@ -116,21 +118,21 @@ 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 );
+ $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 ) {
@@ -138,7 +140,7 @@ class LogPager extends ReverseChronologicalPager {
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 */
@@ -152,9 +154,9 @@ class LogPager extends ReverseChronologicalPager {
// 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';
+ $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) .
+ $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_USER ) .
' != ' . LogPage::SUPPRESSED_USER;
}
$this->performer = $usertitle->getText();
@@ -165,7 +167,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
*/
@@ -207,9 +209,9 @@ 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';
+ $this->mConds[] = $db->bitAnd( 'log_deleted', LogPage::DELETED_ACTION) . ' = 0';
} elseif( !$user->isAllowed( 'suppressrevision' ) ) {
- $this->mConds[] = $db->bitAnd('log_deleted', LogPage::SUPPRESSED_ACTION) .
+ $this->mConds[] = $db->bitAnd( 'log_deleted', LogPage::SUPPRESSED_ACTION) .
' != ' . LogPage::SUPPRESSED_ACTION;
}
}
@@ -249,10 +251,10 @@ class LogPager extends ReverseChronologicalPager {
# avoids site-breaking filesorts.
} elseif( $this->title || $this->pattern || $this->performer ) {
$index['logging'] = array( 'page_time', 'user_time' );
- if( count($this->types) == 1 ) {
+ if( count( $this->types ) == 1 ) {
$index['logging'][] = 'log_user_type_time';
}
- } elseif( count($this->types) == 1 ) {
+ } elseif( count( $this->types ) == 1 ) {
$index['logging'] = 'type_time';
} else {
$index['logging'] = 'times';