diff options
Diffstat (limited to 'includes/logging')
-rw-r--r-- | includes/logging/LogEntry.php | 43 | ||||
-rw-r--r-- | includes/logging/LogEventsList.php | 347 | ||||
-rw-r--r-- | includes/logging/LogFormatter.php | 393 | ||||
-rw-r--r-- | includes/logging/LogPage.php | 72 | ||||
-rw-r--r-- | includes/logging/LogPager.php | 2 | ||||
-rw-r--r-- | includes/logging/PatrolLog.php | 53 |
6 files changed, 589 insertions, 321 deletions
diff --git a/includes/logging/LogEntry.php b/includes/logging/LogEntry.php index 4aa6a826..37560d80 100644 --- a/includes/logging/LogEntry.php +++ b/includes/logging/LogEntry.php @@ -7,6 +7,21 @@ * - formatting log entries based on database fields * - user is now part of the action message * + * 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 @@ -97,6 +112,7 @@ abstract class LogEntryBase implements LogEntry { /** * Whether the parameters for this log are stored in new or * old format. + * @return bool */ public function isLegacy() { return false; @@ -344,7 +360,7 @@ class ManualLogEntry extends LogEntryBase { * * @since 1.19 * - * @param $parameters Associative array + * @param $parameters array Associative array */ public function setParameters( $parameters ) { $this->parameters = $parameters; @@ -431,7 +447,7 @@ class ManualLogEntry extends LogEntryBase { 'log_user_text' => $this->getPerformer()->getName(), 'log_namespace' => $this->getTarget()->getNamespace(), 'log_title' => $this->getTarget()->getDBkey(), - 'log_page' => $this->getTarget()->getArticleId(), + 'log_page' => $this->getTarget()->getArticleID(), 'log_comment' => $comment, 'log_params' => serialize( (array) $this->getParameters() ), ); @@ -457,18 +473,29 @@ class ManualLogEntry extends LogEntryBase { $logpage = SpecialPage::getTitleFor( 'Log', $this->getType() ); $user = $this->getPerformer(); + $ip = ""; + if ( $user->isAnon() ) { + /* + * "MediaWiki default" and friends may have + * no IP address in their name + */ + if ( IP::isIPAddress( $user->getName() ) ) { + $ip = $user->getName(); + } + } $rc = RecentChange::newLogEntry( $this->getTimestamp(), $logpage, $user, - $formatter->getIRCActionText(), // Used for IRC feeds - $user->isAnon() ? $user->getName() : '', + $formatter->getPlainActionText(), + $ip, $this->getType(), $this->getSubtype(), $this->getTarget(), $this->getComment(), serialize( (array) $this->getParameters() ), - $newId + $newId, + $formatter->getIRCActionComment() // Used for IRC feeds ); if ( $to === 'rc' || $to === 'rcandudp' ) { @@ -494,10 +521,16 @@ class ManualLogEntry extends LogEntryBase { return $this->parameters; } + /** + * @return User + */ public function getPerformer() { return $this->performer; } + /** + * @return Title + */ public function getTarget() { return $this->target; } diff --git a/includes/logging/LogEventsList.php b/includes/logging/LogEventsList.php index 437670d0..4de1a974 100644 --- a/includes/logging/LogEventsList.php +++ b/includes/logging/LogEventsList.php @@ -23,52 +23,47 @@ * @file */ -class LogEventsList { +class LogEventsList extends ContextSource { const NO_ACTION_LINK = 1; const NO_EXTRA_USER_LINKS = 2; + const USE_REVDEL_CHECKBOXES = 4; - /** - * @var Skin - */ - private $skin; - - /** - * @var OutputPage - */ - private $out; public $flags; /** * @var Array */ - protected $message; + protected $mDefaultQuery; /** - * @var Array + * Constructor. + * The first two parameters used to be $skin and $out, but now only a context + * is needed, that's why there's a second unused parameter. + * + * @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, + * self::NO_EXTRA_USER_LINKS or self::USE_REVDEL_CHECKBOXES. */ - protected $mDefaultQuery; + public function __construct( $context, $unused = null, $flags = 0 ) { + if ( $context instanceof IContextSource ) { + $this->setContext( $context ); + } else { + // Old parameters, $context should be a Skin object + $this->setContext( $context->getContext() ); + } - public function __construct( $skin, $out, $flags = 0 ) { - $this->skin = $skin; - $this->out = $out; $this->flags = $flags; - $this->preCacheMessages(); } /** - * As we use the same small set of messages in various methods and that - * they are called often, we call them once and save them in $this->message + * Deprecated alias for getTitle(); do not use. + * + * @deprecated in 1.20; use getTitle() instead. + * @return Title object */ - private function preCacheMessages() { - // Precache various messages - if( !isset( $this->message ) ) { - $messages = array( 'revertmerge', 'protect_change', 'unblocklink', 'change-blocklink', - 'revertmove', 'undeletelink', 'undeleteviewlink', 'revdel-restore', 'hist', 'diff', - 'pipe-separator', 'revdel-restore-deleted', 'revdel-restore-visible' ); - foreach( $messages as $msg ) { - $this->message[$msg] = wfMsgExt( $msg, array( 'escapenoentities' ) ); - } - } + public function getDisplayTitle() { + return $this->getTitle(); } /** @@ -80,12 +75,13 @@ class LogEventsList { wfDeprecated( __METHOD__, '1.19' ); // If only one log type is used, then show a special message... $headerType = (count($type) == 1) ? $type[0] : ''; + $out = $this->getOutput(); if( LogPage::isLogType( $headerType ) ) { $page = new LogPage( $headerType ); - $this->out->setPageTitle( $page->getName()->text() ); - $this->out->addHTML( $page->getDescription()->parseAsBlock() ); + $out->setPageTitle( $page->getName()->text() ); + $out->addHTML( $page->getDescription()->parseAsBlock() ); } else { - $this->out->addHTML( wfMsgExt('alllogstext',array('parseinline')) ); + $out->addHTML( $this->msg( 'alllogstext' )->parse() ); } } @@ -105,16 +101,14 @@ class LogEventsList { $month = '', $filter = null, $tagFilter='' ) { global $wgScript, $wgMiserMode; - $action = $wgScript; $title = SpecialPage::getTitleFor( 'Log' ); - $special = $title->getPrefixedDBkey(); // For B/C, we take strings, but make sure they are converted... $types = ($types === '') ? array() : (array)$types; $tagSelector = ChangeTags::buildTagFilterSelector( $tagFilter ); - $html = Html::hidden( 'title', $special ); + $html = Html::hidden( 'title', $title->getPrefixedDBkey() ); // Basic selectors $html .= $this->getTypeMenu( $types ) . "\n"; @@ -141,15 +135,15 @@ class LogEventsList { } // Submit button - $html .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ); + $html .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ); // Fieldset - $html = Xml::fieldset( wfMsg( 'log' ), $html ); + $html = Xml::fieldset( $this->msg( 'log' )->text(), $html ); // Form wrapping - $html = Xml::tags( 'form', array( 'action' => $action, 'method' => 'get' ), $html ); + $html = Xml::tags( 'form', array( 'action' => $wgScript, 'method' => 'get' ), $html ); - $this->out->addHTML( $html ); + $this->getOutput()->addHTML( $html ); } /** @@ -157,9 +151,8 @@ class LogEventsList { * @return String: Formatted HTML */ private function getFilterLinks( $filter ) { - global $wgLang; // show/hide links - $messages = array( wfMsgHtml( 'show' ), wfMsgHtml( 'hide' ) ); + $messages = array( $this->msg( 'show' )->escaped(), $this->msg( 'hide' )->escaped() ); // Option value -> message mapping $links = array(); $hiddens = ''; // keep track for "go" button @@ -172,26 +165,23 @@ class LogEventsList { $hideVal = 1 - intval($val); $query[$queryKey] = $hideVal; - $link = Linker::link( - $this->getDisplayTitle(), + $link = Linker::linkKnown( + $this->getTitle(), $messages[$hideVal], array(), - $query, - array( 'known', 'noclasses' ) + $query ); - $links[$type] = wfMsgHtml( "log-show-hide-{$type}", $link ); + $links[$type] = $this->msg( "log-show-hide-{$type}" )->rawParams( $link )->escaped(); $hiddens .= Html::hidden( "hide_{$type}_log", $val ) . "\n"; } // Build links - return '<small>'.$wgLang->pipeList( $links ) . '</small>' . $hiddens; + return '<small>'.$this->getLanguage()->pipeList( $links ) . '</small>' . $hiddens; } private function getDefaultQuery() { - global $wgRequest; - if ( !isset( $this->mDefaultQuery ) ) { - $this->mDefaultQuery = $wgRequest->getQueryValues(); + $this->mDefaultQuery = $this->getRequest()->getQueryValues(); unset( $this->mDefaultQuery['title'] ); unset( $this->mDefaultQuery['dir'] ); unset( $this->mDefaultQuery['offset'] ); @@ -204,20 +194,6 @@ class LogEventsList { } /** - * Get the Title object of the page the links should point to. - * This is NOT the Title of the page the entries should be restricted to. - * - * @return Title object - */ - public function getDisplayTitle() { - return $this->out->getTitle(); - } - - public function getContext() { - return $this->out->getContext(); - } - - /** * @param $queryTypes Array * @return String: Formatted HTML */ @@ -234,14 +210,12 @@ class LogEventsList { * @since 1.19 */ public function getTypeSelector() { - global $wgUser; - $typesByName = array(); // Temporary array // First pass to load the log names foreach( LogPage::validTypes() as $type ) { $page = new LogPage( $type ); $restriction = $page->getRestriction(); - if ( $wgUser->isAllowed( $restriction ) ) { + if ( $this->getUser()->isAllowed( $restriction ) ) { $typesByName[$type] = $page->getName()->text(); } } @@ -268,7 +242,7 @@ class LogEventsList { */ private function getUserInput( $user ) { return '<span style="white-space: nowrap">' . - Xml::inputLabel( wfMsg( 'specialloguserlabel' ), 'user', 'mw-log-user', 15, $user ) . + Xml::inputLabel( $this->msg( 'specialloguserlabel' )->text(), 'user', 'mw-log-user', 15, $user ) . '</span>'; } @@ -278,7 +252,7 @@ class LogEventsList { */ private function getTitleInput( $title ) { return '<span style="white-space: nowrap">' . - Xml::inputLabel( wfMsg( 'speciallogtitlelabel' ), 'page', 'mw-log-page', 20, $title ) . + Xml::inputLabel( $this->msg( 'speciallogtitlelabel' )->text(), 'page', 'mw-log-page', 20, $title ) . '</span>'; } @@ -288,7 +262,7 @@ class LogEventsList { */ private function getTitlePattern( $pattern ) { return '<span style="white-space: nowrap">' . - Xml::checkLabel( wfMsg( 'log-title-wildcard' ), 'pattern', 'pattern', $pattern ) . + Xml::checkLabel( $this->msg( 'log-title-wildcard' )->text(), 'pattern', 'pattern', $pattern ) . '</span>'; } @@ -297,14 +271,13 @@ class LogEventsList { * @return string */ private function getExtraInputs( $types ) { - global $wgRequest; - $offender = $wgRequest->getVal('offender'); + $offender = $this->getRequest()->getVal( 'offender' ); $user = User::newFromName( $offender, false ); if( !$user || ($user->getId() == 0 && !IP::isIPAddress($offender) ) ) { $offender = ''; // Blank field if invalid } if( count($types) == 1 && $types[0] == 'suppress' ) { - return Xml::inputLabel( wfMsg('revdelete-offender'), 'offender', + return Xml::inputLabel( $this->msg( 'revdelete-offender' )->text(), 'offender', 'mw-log-offender', 20, $offender ); } return ''; @@ -331,169 +304,38 @@ class LogEventsList { public function logLine( $row ) { $entry = DatabaseLogEntry::newFromRow( $row ); $formatter = LogFormatter::newFromEntry( $entry ); + $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() ) ); + $action = $formatter->getActionText(); - $comment = $formatter->getComment(); - $classes = array( 'mw-logline-' . $entry->getType() ); - $title = $entry->getTarget(); - $time = $this->logTimestamp( $entry ); + if ( $this->flags & self::NO_ACTION_LINK ) { + $revert = ''; + } else { + $revert = $formatter->getActionLinks(); + if ( $revert != '' ) { + $revert = '<span class="mw-logevent-actionlink">' . $revert . '</span>'; + } + } - // Extract extra parameters - $paramArray = LogPage::extractParams( $row->log_params ); - // Add review/revert links and such... - $revert = $this->logActionLinks( $row, $title, $paramArray, $comment ); + $comment = $formatter->getComment(); // Some user can hide log items and have review links $del = $this->getShowHideLinks( $row ); - if( $del != '' ) $del .= ' '; // Any tags... list( $tagDisplay, $newClasses ) = ChangeTags::formatSummaryRow( $row->ts_tags, 'logevent' ); - $classes = array_merge( $classes, $newClasses ); - - return Xml::tags( 'li', array( "class" => implode( ' ', $classes ) ), - $del . "$time $action $comment $revert $tagDisplay" ) . "\n"; - } - - private function logTimestamp( LogEntry $entry ) { - global $wgLang; - $time = $wgLang->timeanddate( wfTimestamp( TS_MW, $entry->getTimestamp() ), true ); - return htmlspecialchars( $time ); - } + $classes = array_merge( + array( 'mw-logline-' . $entry->getType() ), + $newClasses + ); - /** - * @TODO: split up! - * - * @param $row - * @param Title $title - * @param Array $paramArray - * @param $comment - * @return String - */ - private function logActionLinks( $row, $title, $paramArray, &$comment ) { - global $wgUser; - if( ( $this->flags & self::NO_ACTION_LINK ) // we don't want to see the action - || self::isDeleted( $row, LogPage::DELETED_ACTION ) ) // action is hidden - { - return ''; - } - $revert = ''; - if( self::typeAction( $row, 'move', 'move', 'move' ) && !empty( $paramArray[0] ) ) { - $destTitle = Title::newFromText( $paramArray[0] ); - if( $destTitle ) { - $revert = '(' . Linker::link( - SpecialPage::getTitleFor( 'Movepage' ), - $this->message['revertmove'], - array(), - array( - 'wpOldTitle' => $destTitle->getPrefixedDBkey(), - 'wpNewTitle' => $title->getPrefixedDBkey(), - 'wpReason' => wfMsgForContent( 'revertmove' ), - 'wpMovetalk' => 0 - ), - array( 'known', 'noclasses' ) - ) . ')'; - } - // Show undelete link - } elseif( self::typeAction( $row, array( 'delete', 'suppress' ), 'delete', 'deletedhistory' ) ) { - if( !$wgUser->isAllowed( 'undelete' ) ) { - $viewdeleted = $this->message['undeleteviewlink']; - } else { - $viewdeleted = $this->message['undeletelink']; - } - $revert = '(' . Linker::link( - SpecialPage::getTitleFor( 'Undelete' ), - $viewdeleted, - array(), - array( 'target' => $title->getPrefixedDBkey() ), - array( 'known', 'noclasses' ) - ) . ')'; - // Show unblock/change block link - } elseif( self::typeAction( $row, array( 'block', 'suppress' ), array( 'block', 'reblock' ), 'block' ) ) { - $revert = '(' . - Linker::link( - SpecialPage::getTitleFor( 'Unblock', $row->log_title ), - $this->message['unblocklink'], - array(), - array(), - 'known' - ) . - $this->message['pipe-separator'] . - Linker::link( - SpecialPage::getTitleFor( 'Block', $row->log_title ), - $this->message['change-blocklink'], - array(), - array(), - 'known' - ) . - ')'; - // Show change protection link - } elseif( self::typeAction( $row, 'protect', array( 'modify', 'protect', 'unprotect' ) ) ) { - $revert .= ' (' . - Linker::link( $title, - $this->message['hist'], - array(), - array( - 'action' => 'history', - 'offset' => $row->log_timestamp - ) - ); - if( $wgUser->isAllowed( 'protect' ) ) { - $revert .= $this->message['pipe-separator'] . - Linker::link( $title, - $this->message['protect_change'], - array(), - array( 'action' => 'protect' ), - 'known' ); - } - $revert .= ')'; - // Show unmerge link - } elseif( self::typeAction( $row, 'merge', 'merge', 'mergehistory' ) ) { - $revert = '(' . Linker::link( - SpecialPage::getTitleFor( 'MergeHistory' ), - $this->message['revertmerge'], - array(), - array( - 'target' => $paramArray[0], - 'dest' => $title->getPrefixedDBkey(), - 'mergepoint' => $paramArray[1] - ), - array( 'known', 'noclasses' ) - ) . ')'; - // If an edit was hidden from a page give a review link to the history - } elseif( self::typeAction( $row, array( 'delete', 'suppress' ), 'revision', 'deletedhistory' ) ) { - $revert = RevisionDeleter::getLogLinks( $title, $paramArray, - $this->message ); - // Hidden log items, give review link - } elseif( self::typeAction( $row, array( 'delete', 'suppress' ), 'event', 'deletedhistory' ) ) { - if( count($paramArray) >= 1 ) { - $revdel = SpecialPage::getTitleFor( 'Revisiondelete' ); - // $paramArray[1] is a CSV of the IDs - $query = $paramArray[0]; - // Link to each hidden object ID, $paramArray[1] is the url param - $revert = '(' . Linker::link( - $revdel, - $this->message['revdel-restore'], - array(), - array( - 'target' => $title->getPrefixedText(), - 'type' => 'logging', - 'ids' => $query - ), - array( 'known', 'noclasses' ) - ) . ')'; - } - // Do nothing. The implementation is handled by the hook modifiying the passed-by-ref parameters. - } else { - wfRunHooks( 'LogLine', array( $row->log_type, $row->log_action, $title, $paramArray, - &$comment, &$revert, $row->log_timestamp ) ); - } - if( $revert != '' ) { - $revert = '<span class="mw-logevent-actionlink">' . $revert . '</span>'; - } - return $revert; + return Html::rawElement( 'li', array( 'class' => $classes ), + "$del $time $action $comment $revert $tagDisplay" ) . "\n"; } /** @@ -501,28 +343,33 @@ class LogEventsList { * @return string */ private function getShowHideLinks( $row ) { - global $wgUser; - 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 = ''; - // Don't show useless link to people who cannot hide revisions - if( $wgUser->isAllowed( 'deletedhistory' ) ) { - if( $row->log_deleted || $wgUser->isAllowed( 'deleterevision' ) ) { - $canHide = $wgUser->isAllowed( 'deleterevision' ); - // If event was hidden from sysops - if( !self::userCan( $row, LogPage::DELETED_RESTRICTED ) ) { - $del = Linker::revDeleteLinkDisabled( $canHide ); + $user = $this->getUser(); + // Don't show useless checkbox to people who cannot hide log entries + if( $user->isAllowed( 'deletedhistory' ) ) { + if( $row->log_deleted || $user->isAllowed( 'deletelogentry' ) ) { + $canHide = $user->isAllowed( 'deletelogentry' ); + if ( $this->flags & self::USE_REVDEL_CHECKBOXES ) { // Show checkboxes instead of links. + if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) { // If event was hidden from sysops + $del = Xml::check( 'deleterevisions', false, array( 'disabled' => 'disabled' ) ); + } else { + $del = Xml::check( 'showhiderevisions', false, array( 'name' => 'ids[' . $row->log_id . ']' ) ); + } } else { - $target = SpecialPage::getTitleFor( 'Log', $row->log_type ); - $query = array( - 'target' => $target->getPrefixedDBkey(), - 'type' => 'logging', - 'ids' => $row->log_id, - ); - $del = Linker::revDeleteLink( $query, - self::isDeleted( $row, LogPage::DELETED_RESTRICTED ), $canHide ); + if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) { // If event was hidden from sysops + $del = Linker::revDeleteLinkDisabled( $canHide ); + } else { + $query = array( + 'target' => SpecialPage::getTitleFor( 'Log', $row->log_type )->getPrefixedDBkey(), + 'type' => 'logging', + 'ids' => $row->log_id, + ); + $del = Linker::revDeleteLink( $query, self::isDeleted( $row, LogPage::DELETED_RESTRICTED ), $canHide ); + } } } } @@ -606,15 +453,15 @@ class LogEventsList { * @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 Associative Array with the following additional options: + * @param $param array 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 * if set to true (default), "No matching items in log" is displayed if loglist is empty * - msgKey Array If you want a nice box with a message, set this to the key of the message. * First element is the message key, additional optional elements are parameters for the key - * that are processed with wfMsgExt and option 'parse' - * - offset Set to overwrite offset parameter in $wgRequest + * that are processed with wfMessage + * - offset Set to overwrite offset parameter in WebRequest * 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) @@ -652,9 +499,9 @@ class LogEventsList { } # Insert list of top 50 (or top $lim) items - $loglist = new LogEventsList( $context->getSkin(), $context->getOutput(), $flags ); + $loglist = new LogEventsList( $context, null, $flags ); $pager = new LogPager( $loglist, $types, $user, $page, '', $conds ); - if ( isset( $param['offset'] ) ) { # Tell pager to ignore $wgRequest offset + if ( isset( $param['offset'] ) ) { # Tell pager to ignore WebRequest offset $pager->setOffset( $param['offset'] ); } if( $lim > 0 ) $pager->mLimit = $lim; @@ -665,11 +512,11 @@ class LogEventsList { $s = '<div class="mw-warning-with-logexcerpt">'; if ( count( $msgKey ) == 1 ) { - $s .= wfMsgExt( $msgKey[0], array( 'parse' ) ); + $s .= $context->msg( $msgKey[0] )->parseAsBlock(); } else { // Process additional arguments $args = $msgKey; array_shift( $args ); - $s .= wfMsgExt( $msgKey[0], array( 'parse' ), $args ); + $s .= $context->msg( $msgKey[0], $args )->parseAsBlock(); } } $s .= $loglist->beginLogEventsList() . @@ -678,7 +525,7 @@ class LogEventsList { } else { if ( $showIfEmpty ) { $s = Html::rawElement( 'div', array( 'class' => 'mw-warning-logempty' ), - wfMsgExt( 'logempty', array( 'parseinline' ) ) ); + $context->msg( 'logempty' )->parse() ); } } if( $pager->getNumRows() > $pager->mLimit ) { # Show "Full log" link @@ -697,7 +544,7 @@ class LogEventsList { $urlParam['type'] = $types[0]; $s .= Linker::link( SpecialPage::getTitleFor( 'Log' ), - wfMsgHtml( 'log-fulllog' ), + $context->msg( 'log-fulllog' )->escaped(), array(), $urlParam ); diff --git a/includes/logging/LogFormatter.php b/includes/logging/LogFormatter.php index 24490eed..7586bb65 100644 --- a/includes/logging/LogFormatter.php +++ b/includes/logging/LogFormatter.php @@ -2,6 +2,21 @@ /** * Contains classes for formatting 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 @@ -94,24 +109,24 @@ class LogFormatter { /** * Set the visibility restrictions for displaying content. - * If set to public, and an item is deleted, then it will be replaced + * If set to public, and an item is deleted, then it will be replaced * with a placeholder even if the context user is allowed to view it. * @param $audience integer self::FOR_THIS_USER or self::FOR_PUBLIC */ public function setAudience( $audience ) { $this->audience = ( $audience == self::FOR_THIS_USER ) - ? self::FOR_THIS_USER + ? self::FOR_THIS_USER : self::FOR_PUBLIC; } /** * Check if a log item can be displayed * @param $field integer LogPage::DELETED_* constant - * @return bool + * @return bool */ protected function canView( $field ) { if ( $this->audience == self::FOR_THIS_USER ) { - return LogEventsList::userCanBitfield( + return LogEventsList::userCanBitfield( $this->entry->getDeleted(), $field, $this->context->getUser() ); } else { return !$this->entry->isDeleted( $field ); @@ -148,14 +163,34 @@ class LogFormatter { * @see getActionText() * @return string text */ + public function getIRCActionComment() { + $actionComment = $this->getIRCActionText(); + $comment = $this->entry->getComment(); + + if ( $comment != '' ) { + if ( $actionComment == '' ) { + $actionComment = $comment; + } else { + $actionComment .= wfMessage( 'colon-separator' )->inContentLanguage()->text() . $comment; + } + } + + return $actionComment; + } + + /** + * Even uglier hack to maintain backwards compatibilty with IRC bots + * (bug 34508). + * @see getActionText() + * @return string text + */ public function getIRCActionText() { $this->plaintext = true; - $text = $this->getActionText(); + $this->irctext = true; $entry = $this->entry; $parameters = $entry->getParameters(); // @see LogPage::actionText() - $msgOpts = array( 'parsemag', 'escape', 'replaceafter', 'content' ); // Text of title the action is aimed at. $target = $entry->getTarget()->getPrefixedText() ; $text = null; @@ -164,11 +199,13 @@ class LogFormatter { switch( $entry->getSubtype() ) { case 'move': $movesource = $parameters['4::target']; - $text = wfMsgExt( '1movedto2', $msgOpts, $target, $movesource ); + $text = wfMessage( '1movedto2' ) + ->rawParams( $target, $movesource )->inContentLanguage()->escaped(); break; case 'move_redir': $movesource = $parameters['4::target']; - $text = wfMsgExt( '1movedto2_redir', $msgOpts, $target, $movesource ); + $text = wfMessage( '1movedto2_redir' ) + ->rawParams( $target, $movesource )->inContentLanguage()->escaped(); break; case 'move-noredirect': break; @@ -180,10 +217,12 @@ class LogFormatter { case 'delete': switch( $entry->getSubtype() ) { case 'delete': - $text = wfMsgExt( 'deletedarticle', $msgOpts, $target ); + $text = wfMessage( 'deletedarticle' ) + ->rawParams( $target )->inContentLanguage()->escaped(); break; case 'restore': - $text = wfMsgExt( 'undeletedarticle', $msgOpts, $target ); + $text = wfMessage( 'undeletedarticle' ) + ->rawParams( $target )->inContentLanguage()->escaped(); break; //case 'revision': // Revision deletion //case 'event': // Log deletion @@ -197,24 +236,46 @@ class LogFormatter { // Create a diff link to the patrolled revision if ( $entry->getSubtype() === 'patrol' ) { $diffLink = htmlspecialchars( - wfMsgForContent( 'patrol-log-diff', $parameters['4::curid'] ) ); - $text = wfMsgForContent( 'patrol-log-line', $diffLink, "[[$target]]", "" ); + wfMessage( 'patrol-log-diff', $parameters['4::curid'] ) + ->inContentLanguage()->text() ); + $text = wfMessage( 'patrol-log-line', $diffLink, "[[$target]]", "" ) + ->inContentLanguage()->text(); } else { // broken?? } break; + case 'protect': + switch( $entry->getSubtype() ) { + case 'protect': + $text = wfMessage( 'protectedarticle' ) + ->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped(); + break; + case 'unprotect': + $text = wfMessage( 'unprotectedarticle' ) + ->rawParams( $target )->inContentLanguage()->escaped(); + break; + case 'modify': + $text = wfMessage( 'modifiedarticleprotection' ) + ->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped(); + break; + } + break; + case 'newusers': switch( $entry->getSubtype() ) { case 'newusers': case 'create': - $text = wfMsgExt( 'newuserlog-create-entry', $msgOpts /* no params */ ); + $text = wfMessage( 'newuserlog-create-entry' ) + ->inContentLanguage()->escaped(); break; case 'create2': - $text = wfMsgExt( 'newuserlog-create2-entry', $msgOpts, $target ); + $text = wfMessage( 'newuserlog-create2-entry' ) + ->rawParams( $target )->inContentLanguage()->escaped(); break; case 'autocreate': - $text = wfMsgExt( 'newuserlog-autocreate-entry', $msgOpts /* no params */ ); + $text = wfMessage( 'newuserlog-autocreate-entry' ) + ->inContentLanguage()->escaped(); break; } break; @@ -222,14 +283,17 @@ class LogFormatter { case 'upload': switch( $entry->getSubtype() ) { case 'upload': - $text = wfMsgExt( 'uploadedimage', $msgOpts, $target ); + $text = wfMessage( 'uploadedimage' ) + ->rawParams( $target )->inContentLanguage()->escaped(); break; case 'overwrite': - $text = wfMsgExt( 'overwroteimage', $msgOpts, $target ); + $text = wfMessage( 'overwroteimage' ) + ->rawParams( $target )->inContentLanguage()->escaped(); break; } break; + // case 'suppress' --private log -- aaron (sign your messages so we know who to blame in a few years :-D) // default: } @@ -238,6 +302,7 @@ class LogFormatter { } $this->plaintext = false; + $this->irctext = false; return $text; } @@ -266,7 +331,7 @@ class LogFormatter { * Returns a sentence describing the log action. Usually * a Message object is returned, but old style log types * and entries might return pre-escaped html string. - * @return Message|pre-escaped html + * @return Message|string pre-escaped html */ protected function getActionMessage() { $message = $this->msg( $this->getMessageKey() ); @@ -289,6 +354,15 @@ class LogFormatter { } /** + * Returns extra links that comes after the action text, like "revert", etc. + * + * @return string + */ + public function getActionLinks() { + return ''; + } + + /** * Extracts the optional extra parameters for use in action messages. * The array indexes start from number 3. * @return array @@ -373,6 +447,7 @@ class LogFormatter { * Provides the name of the user who performed the log action. * Used as part of log action message or standalone, depending * which parts of the log entry has been hidden. + * @return String */ public function getPerformerElement() { if ( $this->canView( LogPage::DELETED_USER ) ) { @@ -442,9 +517,7 @@ class LogFormatter { * @return Message */ protected function msg( $key ) { - return wfMessage( $key ) - ->inLanguage( $this->context->getLanguage() ) - ->title( $this->context->getTitle() ); + return $this->context->msg( $key ); } protected function makeUserLink( User $user ) { @@ -457,11 +530,9 @@ class LogFormatter { ); if ( $this->linkFlood ) { - $element .= Linker::userToolLinks( + $element .= Linker::userToolLinksRedContribs( $user->getId(), $user->getName(), - true, // Red if no edits - 0, // Flags $user->getEditCount() ); } @@ -488,6 +559,41 @@ class LogFormatter { * @since 1.19 */ class LegacyLogFormatter extends LogFormatter { + + /** + * Backward compatibility for extension changing the comment from + * the LogLine hook. This will be set by the first call on getComment(), + * then it might be modified by the hook when calling getActionLinks(), + * so that the modified value will be returned when calling getComment() + * a second time. + * + * @var string|null + */ + private $comment = null; + + /** + * Cache for the result of getActionLinks() so that it does not need to + * run multiple times depending on the order that getComment() and + * getActionLinks() are called. + * + * @var string|null + */ + private $revert = null; + + public function getComment() { + if ( $this->comment === null ) { + $this->comment = parent::getComment(); + } + + // Make sure we execute the LogLine hook so that we immediately return + // the correct value. + if ( $this->revert === null ) { + $this->getActionLinks(); + } + + return $this->comment; + } + protected function getActionMessage() { $entry = $this->entry; $action = LogPage::actionText( @@ -500,9 +606,104 @@ class LegacyLogFormatter extends LogFormatter { ); $performer = $this->getPerformerElement(); - return $performer . $this->msg( 'word-separator' )->text() . $action; + if ( !$this->irctext ) { + $action = $performer . $this->msg( 'word-separator' )->text() . $action; + } + + return $action; } + public function getActionLinks() { + if ( $this->revert !== null ) { + return $this->revert; + } + + if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) { + return $this->revert = ''; + } + + $title = $this->entry->getTarget(); + $type = $this->entry->getType(); + $subtype = $this->entry->getSubtype(); + + // Show unblock/change block link + if ( ( $type == 'block' || $type == 'suppress' ) && ( $subtype == 'block' || $subtype == 'reblock' ) ) { + if ( !$this->context->getUser()->isAllowed( 'block' ) ) { + return ''; + } + + $links = array( + Linker::linkKnown( + SpecialPage::getTitleFor( 'Unblock', $title->getDBkey() ), + $this->msg( 'unblocklink' )->escaped() + ), + Linker::linkKnown( + SpecialPage::getTitleFor( 'Block', $title->getDBkey() ), + $this->msg( 'change-blocklink' )->escaped() + ) + ); + return $this->msg( 'parentheses' )->rawParams( + $this->context->getLanguage()->pipeList( $links ) )->escaped(); + // Show change protection link + } elseif ( $type == 'protect' && ( $subtype == 'protect' || $subtype == 'modify' || $subtype == 'unprotect' ) ) { + $links = array( + Linker::link( $title, + $this->msg( 'hist' )->escaped(), + array(), + array( + 'action' => 'history', + 'offset' => $this->entry->getTimestamp() + ) + ) + ); + if ( $this->context->getUser()->isAllowed( 'protect' ) ) { + $links[] = Linker::linkKnown( + $title, + $this->msg( 'protect_change' )->escaped(), + array(), + array( 'action' => 'protect' ) + ); + } + return $this->msg( 'parentheses' )->rawParams( + $this->context->getLanguage()->pipeList( $links ) )->escaped(); + // Show unmerge link + } elseif( $type == 'merge' && $subtype == 'merge' ) { + if ( !$this->context->getUser()->isAllowed( 'mergehistory' ) ) { + return ''; + } + + $params = $this->extractParameters(); + $revert = Linker::linkKnown( + SpecialPage::getTitleFor( 'MergeHistory' ), + $this->msg( 'revertmerge' )->escaped(), + array(), + array( + 'target' => $params[3], + 'dest' => $title->getPrefixedDBkey(), + 'mergepoint' => $params[4] + ) + ); + return $this->msg( 'parentheses' )->rawParams( $revert )->escaped(); + } + + // Do nothing. The implementation is handled by the hook modifiying the + // passed-by-ref parameters. This also changes the default value so that + // getComment() and getActionLinks() do not call them indefinitely. + $this->revert = ''; + + // This is to populate the $comment member of this instance so that it + // can be modified when calling the hook just below. + if ( $this->comment === null ) { + $this->getComment(); + } + + $params = $this->entry->getParameters(); + + wfRunHooks( 'LogLine', array( $type, $subtype, $title, $params, + &$this->comment, &$this->revert, $this->entry->getTimestamp() ) ); + + return $this->revert; + } } /** @@ -532,6 +733,34 @@ class MoveLogFormatter extends LogFormatter { $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(); + } } /** @@ -601,6 +830,107 @@ class DeleteLogFormatter extends LogFormatter { 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 ''; + } + } } /** @@ -619,7 +949,6 @@ class PatrolLogFormatter extends LogFormatter { protected function getMessageParameters() { $params = parent::getMessageParameters(); - $newParams = array_slice( $params, 0, 3 ); $target = $this->entry->getTarget(); $oldid = $params[3]; @@ -637,8 +966,8 @@ class PatrolLogFormatter extends LogFormatter { $revlink = htmlspecialchars( $revision ); } - $newParams[3] = Message::rawParam( $revlink ); - return $newParams; + $params[3] = Message::rawParam( $revlink ); + return $params; } } @@ -670,4 +999,12 @@ class NewUsersLogFormatter extends LogFormatter { } return parent::getComment(); } + + public function getPreloadTitles() { + if ( $this->entry->getSubtype() === 'create2' ) { + //add the user talk to LinkBatch for the userLink + return array( Title::makeTitle( NS_USER_TALK, $this->entry->getTarget()->getText() ) ); + } + return array(); + } } diff --git a/includes/logging/LogPage.php b/includes/logging/LogPage.php index bbb4de8f..d96a5ea5 100644 --- a/includes/logging/LogPage.php +++ b/includes/logging/LogPage.php @@ -68,7 +68,7 @@ class LogPage { } /** - * @return bool|int|null + * @return int log_id of the inserted log entry */ protected function saveContent() { global $wgLogRestrictions; @@ -86,7 +86,7 @@ class LogPage { 'log_user_text' => $this->doer->getName(), 'log_namespace' => $this->target->getNamespace(), 'log_title' => $this->target->getDBkey(), - 'log_page' => $this->target->getArticleId(), + 'log_page' => $this->target->getArticleID(), 'log_comment' => $this->comment, 'log_params' => $this->params ); @@ -100,12 +100,12 @@ class LogPage { RecentChange::notifyLog( $now, $titleObj, $this->doer, $this->getRcComment(), '', $this->type, $this->action, $this->target, $this->comment, - $this->params, $newId + $this->params, $newId, $this->getRcCommentIRC() ); } elseif( $this->sendToUDP ) { # Don't send private logs to UDP if( isset( $wgLogRestrictions[$this->type] ) && $wgLogRestrictions[$this->type] != '*' ) { - return true; + return $newId; } # Notify external application via UDP. @@ -114,7 +114,7 @@ class LogPage { $rc = RecentChange::newLogEntry( $now, $titleObj, $this->doer, $this->getRcComment(), '', $this->type, $this->action, $this->target, $this->comment, - $this->params, $newId + $this->params, $newId, $this->getRcCommentIRC() ); $rc->notifyRC2UDP(); } @@ -133,7 +133,28 @@ class LogPage { if ( $rcComment == '' ) { $rcComment = $this->comment; } else { - $rcComment .= wfMsgForContent( 'colon-separator' ) . $this->comment; + $rcComment .= wfMessage( 'colon-separator' )->inContentLanguage()->text() . + $this->comment; + } + } + + return $rcComment; + } + + /** + * Get the RC comment from the last addEntry() call for IRC + * + * @return string + */ + public function getRcCommentIRC() { + $rcComment = $this->ircActionText; + + if( $this->comment != '' ) { + if ( $rcComment == '' ) { + $rcComment = $this->comment; + } else { + $rcComment .= wfMessage( 'colon-separator' )->inContentLanguage()->text() . + $this->comment; } } @@ -175,11 +196,10 @@ class LogPage { * @deprecated in 1.19, warnings in 1.21. Use getName() */ public static function logName( $type ) { - wfDeprecated( __METHOD__, '1.19' ); global $wgLogNames; if( isset( $wgLogNames[$type] ) ) { - return str_replace( '_', ' ', wfMsg( $wgLogNames[$type] ) ); + return str_replace( '_', ' ', wfMessage( $wgLogNames[$type] )->text() ); } else { // Bogus log types? Perhaps an extension was removed. return $type; @@ -195,9 +215,8 @@ class LogPage { * @deprecated in 1.19, warnings in 1.21. Use getDescription() */ public static function logHeader( $type ) { - wfDeprecated( __METHOD__, '1.19' ); global $wgLogHeaders; - return wfMsgExt( $wgLogHeaders[$type], array( 'parseinline' ) ); + return wfMessage( $wgLogHeaders[$type] )->parse(); } /** @@ -230,17 +249,20 @@ class LogPage { if( isset( $wgLogActions[$key] ) ) { if( is_null( $title ) ) { - $rv = wfMsgExt( $wgLogActions[$key], array( 'parsemag', 'escape', 'language' => $langObj ) ); + $rv = wfMessage( $wgLogActions[$key] )->inLanguage( $langObj )->escaped(); } else { $titleLink = self::getTitleLink( $type, $langObjOrNull, $title, $params ); if( preg_match( '/^rights\/(rights|autopromote)/', $key ) ) { - $rightsnone = wfMsgExt( 'rightsnone', array( 'parsemag', 'language' => $langObj ) ); + $rightsnone = wfMessage( 'rightsnone' )->inLanguage( $langObj )->text(); if( $skin ) { + $username = $title->getText(); foreach ( $params as &$param ) { $groupArray = array_map( 'trim', explode( ',', $param ) ); - $groupArray = array_map( array( 'User', 'getGroupMember' ), $groupArray ); + foreach( $groupArray as &$group ) { + $group = User::getGroupMember( $group, $username ); + } $param = $wgLang->listToText( $groupArray ); } } @@ -255,7 +277,7 @@ class LogPage { } if( count( $params ) == 0 ) { - $rv = wfMsgExt( $wgLogActions[$key], array( 'parsemag', 'escape', 'replaceafter', 'language' => $langObj ), $titleLink ); + $rv = wfMessage( $wgLogActions[$key] )->rawParams( $titleLink )->inLanguage( $langObj )->escaped(); } else { $details = ''; array_unshift( $params, $titleLink ); @@ -282,11 +304,11 @@ class LogPage { // Cascading flag... if( $params[2] ) { - $details .= ' [' . wfMsgExt( 'protect-summary-cascade', array( 'parsemag', 'language' => $langObj ) ) . ']'; + $details .= ' [' . wfMessage( 'protect-summary-cascade' )->inLanguage( $langObj )->text() . ']'; } } - $rv = wfMsgExt( $wgLogActions[$key], array( 'parsemag', 'escape', 'replaceafter', 'language' => $langObj ), $params ) . $details; + $rv = wfMessage( $wgLogActions[$key] )->rawParams( $params )->inLanguage( $langObj )->escaped() . $details; } } } else { @@ -399,7 +421,12 @@ class LogPage { # Use the language name for log titles, rather than Log/X if( $name == 'Log' ) { - $titleLink = '(' . Linker::link( $title, LogPage::logName( $par ) ) . ')'; + $logPage = new LogPage( $par ); + $titleLink = Linker::link( $title, $logPage->getName()->escaped() ); + $titleLink = wfMessage( 'parentheses' ) + ->inLanguage( $lang ) + ->rawParams( $titleLink ) + ->escaped(); } else { $titleLink = Linker::link( $title ); } @@ -417,11 +444,10 @@ class LogPage { * @param $action String: 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 wfMsg.* functions + * @param $params Array: parameters passed later to wfMessage function * @param $doer User object: the user doing the action * - * @return bool|int|null - * @TODO: make this use LogEntry::saveContent() + * @return int log_id of the inserted log entry */ public function addEntry( $action, $target, $comment, $params = array(), $doer = null ) { global $wgContLang; @@ -461,6 +487,7 @@ class LogPage { $formatter->setContext( $context ); $this->actionText = $formatter->getPlainActionText(); + $this->ircActionText = $formatter->getIRCActionText(); return $this->saveContent(); } @@ -522,7 +549,7 @@ class LogPage { * Convert a comma-delimited list of block log flags * into a more readable (and translated) form * - * @param $flags Flags to format + * @param $flags string Flags to format * @param $lang Language object to use * @return String */ @@ -533,7 +560,8 @@ class LogPage { for( $i = 0; $i < count( $flags ); $i++ ) { $flags[$i] = self::formatBlockFlag( $flags[$i], $lang ); } - return '(' . $lang->commaList( $flags ) . ')'; + return wfMessage( 'parentheses' )->inLanguage( $lang ) + ->rawParams( $lang->commaList( $flags ) )->escaped(); } else { return ''; } diff --git a/includes/logging/LogPager.php b/includes/logging/LogPager.php index 16781a6e..ea1be8e0 100644 --- a/includes/logging/LogPager.php +++ b/includes/logging/LogPager.php @@ -131,6 +131,7 @@ class LogPager extends ReverseChronologicalPager { * Set the log reader to return only entries by the given user. * * @param $name String: (In)valid user name + * @return bool */ private function limitPerformer( $name ) { if( $name == '' ) { @@ -166,6 +167,7 @@ class LogPager extends ReverseChronologicalPager { * * @param $page String or Title object: Title name * @param $pattern String + * @return bool */ private function limitTitle( $page, $pattern ) { global $wgMiserMode; diff --git a/includes/logging/PatrolLog.php b/includes/logging/PatrolLog.php index 04fdc4f2..911fffc0 100644 --- a/includes/logging/PatrolLog.php +++ b/includes/logging/PatrolLog.php @@ -1,12 +1,31 @@ <?php - /** - * Class containing static functions for working with - * logs of patrol events + * Specific methods for the patrol log. + * + * 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 Rob Church <robchur@gmail.com> * @author Niklas Laxström */ + +/** + * Class containing static functions for working with + * logs of patrol events + */ class PatrolLog { /** @@ -14,10 +33,11 @@ class PatrolLog { * * @param $rc Mixed: change identifier or RecentChange object * @param $auto Boolean: was this patrol event automatic? + * @param $user User: user performing the action or null to use $wgUser * * @return bool */ - public static function record( $rc, $auto = false ) { + public static function record( $rc, $auto = false, User $user = null ) { if ( !$rc instanceof RecentChange ) { $rc = RecentChange::newFromId( $rc ); if ( !is_object( $rc ) ) { @@ -25,19 +45,20 @@ class PatrolLog { } } - $title = Title::makeTitleSafe( $rc->getAttribute( 'rc_namespace' ), $rc->getAttribute( 'rc_title' ) ); - if( $title ) { - $entry = new ManualLogEntry( 'patrol', 'patrol' ); - $entry->setTarget( $title ); - $entry->setParameters( self::buildParams( $rc, $auto ) ); - $entry->setPerformer( User::newFromName( $rc->getAttribute( 'rc_user_text' ), false ) ); - $logid = $entry->insert(); - if ( !$auto ) { - $entry->publish( $logid, 'udp' ); - } - return true; + if ( !$user ) { + global $wgUser; + $user = $wgUser; + } + + $entry = new ManualLogEntry( 'patrol', 'patrol' ); + $entry->setTarget( $rc->getTitle() ); + $entry->setParameters( self::buildParams( $rc, $auto ) ); + $entry->setPerformer( $user ); + $logid = $entry->insert(); + if ( !$auto ) { + $entry->publish( $logid, 'udp' ); } - return false; + return true; } /** |