diff options
Diffstat (limited to 'includes/logging')
-rw-r--r-- | includes/logging/DeleteLogFormatter.php | 196 | ||||
-rw-r--r-- | includes/logging/LogEntry.php | 55 | ||||
-rw-r--r-- | includes/logging/LogEventsList.php | 82 | ||||
-rw-r--r-- | includes/logging/LogFormatter.php | 412 | ||||
-rw-r--r-- | includes/logging/LogPage.php | 62 | ||||
-rw-r--r-- | includes/logging/LogPager.php | 77 | ||||
-rw-r--r-- | includes/logging/MoveLogFormatter.php | 82 | ||||
-rw-r--r-- | includes/logging/NewUsersLogFormatter.php | 65 | ||||
-rw-r--r-- | includes/logging/PatrolLog.php | 7 | ||||
-rw-r--r-- | includes/logging/PatrolLogFormatter.php | 63 | ||||
-rw-r--r-- | includes/logging/RightsLogFormatter.php | 112 |
11 files changed, 692 insertions, 521 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 0f20ed16..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 ); } @@ -233,8 +233,8 @@ class DatabaseLogEntry extends LogEntryBase { } public function getPerformer() { - if( !$this->performer ) { - $userId = (int) $this->row->log_user; + 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 ); @@ -291,8 +291,8 @@ class RCDatabaseLogEntry extends DatabaseLogEntry { } public function getPerformer() { - if( !$this->performer ) { - $userId = (int) $this->row->rc_user; + if ( !$this->performer ) { + $userId = (int)$this->row->rc_user; if ( $userId !== 0 ) { $this->performer = User::newFromId( $userId ); } else { @@ -334,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 @@ -374,6 +375,17 @@ class ManualLogEntry extends LogEntryBase { } /** + * 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 @@ -430,12 +442,13 @@ 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 ) { @@ -459,10 +472,28 @@ 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; } @@ -503,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 ); @@ -513,7 +544,7 @@ class ManualLogEntry extends LogEntryBase { } if ( $to === 'udp' || $to === 'rcandudp' ) { - $rc->notifyRC2UDP(); + $rc->notifyRCFeeds(); } } @@ -555,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 501af7d6..c27b57af 100644 --- a/includes/logging/LogEventsList.php +++ b/includes/logging/LogEventsList.php @@ -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() ); @@ -97,14 +97,14 @@ class LogEventsList extends ContextSource { * @param $filter: array * @param $tagFilter: array? */ - public function showOptions( $types=array(), $user = '', $page = '', $pattern = '', $year = '', + 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 ); @@ -156,7 +156,7 @@ 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(); @@ -172,6 +172,7 @@ 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"; } @@ -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 ) ) { @@ -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 ); } @@ -342,16 +343,16 @@ 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 ( $user->isAllowed( 'deletedhistory' ) ) { $canHide = $user->isAllowed( 'deletelogentry' ); - if( $row->log_deleted || $canHide ) { + 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' ) ); @@ -364,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 ); } @@ -385,10 +386,10 @@ class LogEventsList extends ContextSource { 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 ); } @@ -419,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 { @@ -464,10 +465,11 @@ 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, @@ -475,7 +477,8 @@ class LogEventsList extends ContextSource { 'showIfEmpty' => true, '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. @@ -487,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 ); } @@ -500,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">'; @@ -521,26 +534,27 @@ 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() ); - } + } 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(), @@ -589,14 +603,14 @@ class LogEventsList extends ContextSource { $hiddenLogs = array(); // Don't show private logs to unprivileged users - foreach( $wgLogRestrictions as $logType => $right ) { - if( $audience == 'public' || !$user->isAllowed( $right ) ) { + 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 ) { + } 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 ace26bbe..8f60aee1 100644 --- a/includes/logging/LogFormatter.php +++ b/includes/logging/LogFormatter.php @@ -194,9 +194,9 @@ class LogFormatter { // Text of title the action is aimed at. $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']; $text = wfMessage( '1movedto2' ) @@ -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,7 +263,7 @@ class LogFormatter { break; case 'newusers': - switch( $entry->getSubtype() ) { + switch ( $entry->getSubtype() ) { case 'newusers': case 'create': $text = wfMessage( 'newuserlog-create-entry' ) @@ -282,7 +282,7 @@ class LogFormatter { break; case 'upload': - switch( $entry->getSubtype() ) { + switch ( $entry->getSubtype() ) { case 'upload': $text = wfMessage( 'uploadedimage' ) ->rawParams( $target )->inContentLanguage()->escaped(); @@ -305,7 +305,7 @@ class LogFormatter { } else { $newgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped(); } - switch( $entry->getSubtype() ) { + switch ( $entry->getSubtype() ) { case 'rights': $text = wfMessage( 'rightslogentry' ) ->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped(); @@ -320,7 +320,7 @@ class LogFormatter { // 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(); } @@ -479,7 +479,7 @@ class LogFormatter { protected function formatParameterValue( $type, $value ) { $saveLinkFlood = $this->linkFlood; - switch( strtolower( trim( $type ) ) ) { + switch ( strtolower( trim( $type ) ) ) { case 'raw': $value = Message::rawParam( $value ); break; @@ -775,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 ''; } @@ -814,395 +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' ) ) ) { - // $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 ''; - } - } -} - -/** - * 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(); - $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(); - } -} - -/** - * 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 4191c577..cc473c18 100644 --- a/includes/logging/LogPage.php +++ b/includes/logging/LogPage.php @@ -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 { @@ -198,7 +198,7 @@ class LogPage { 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. @@ -247,13 +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( count( $params ) == 0 ) { + if ( count( $params ) == 0 ) { $rv = wfMessage( $wgLogActions[$key] )->rawParams( $titleLink )->inLanguage( $langObj )->escaped(); } else { $details = ''; @@ -262,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="‎' . htmlspecialchars( $params[1] ) . '">' . $wgLang->translateBlockExpiry( $params[1] ) . '</span>'; } else { $params[1] = $wgContLang->translateBlockExpiry( $params[1] ); @@ -273,14 +273,14 @@ class LogPage { // Page protections } 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() . ']'; } } @@ -291,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 { @@ -310,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 ); } @@ -327,11 +327,11 @@ class LogPage { * @return String */ protected static function getTitleLink( $type, $lang, $title, &$params ) { - if( !$lang ) { + if ( !$lang ) { return $title->getPrefixedText(); } - switch( $type ) { + switch ( $type ) { case 'move': $titleLink = Linker::link( $title, @@ -353,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 @@ -377,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' ) @@ -465,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, @@ -518,17 +518,17 @@ class LogPage { * @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(); } /** @@ -541,7 +541,7 @@ class LogPage { 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: diff --git a/includes/logging/LogPager.php b/includes/logging/LogPager.php index 908755ed..09ae3b8c 100644 --- a/includes/logging/LogPager.php +++ b/includes/logging/LogPager.php @@ -34,14 +34,14 @@ class LogPager extends ReverseChronologicalPager { /** * Constructor * - * @param $list LogEventsList + * @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 $year Integer: the year to start from - * @param $month Integer: the month to start from + * @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 = '', @@ -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; @@ -98,11 +99,11 @@ class LogPager extends ReverseChronologicalPager { $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] ) + if ( isset( $wgLogRestrictions[$type] ) && !$user->isAllowed( $wgLogRestrictions[$type] ) ) { $needReindex = true; @@ -119,13 +120,15 @@ class LogPager extends ReverseChronologicalPager { // Also, only show them upon specific request to avoid suprises. $audience = $types ? 'user' : 'public'; $hideLogs = LogEventsList::getExcludeClause( $this->mDb, $audience, $user ); - if( $hideLogs !== false ) { + 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]; + } } } @@ -136,16 +139,16 @@ class LogPager extends ReverseChronologicalPager { * @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"; @@ -153,9 +156,9 @@ class LogPager extends ReverseChronologicalPager { $this->mConds['log_user'] = $userid; // Paranoia: avoid brute force searches (bug 17342) $user = $this->getUser(); - if( !$user->isAllowed( 'deletedhistory' ) ) { + if ( !$user->isAllowed( 'deletedhistory' ) ) { $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::DELETED_USER ) . ' = 0'; - } elseif( !$user->isAllowed( 'suppressrevision' ) ) { + } elseif ( !$user->isAllowed( 'suppressrevision' ) ) { $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_USER ) . ' != ' . LogPage::SUPPRESSED_USER; } @@ -178,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; } } @@ -198,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; @@ -208,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; } } @@ -234,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'; @@ -246,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 @@ -295,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; + } +} |