diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2015-12-20 09:00:55 +0100 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2015-12-20 09:00:55 +0100 |
commit | a2190ac74dd4d7080b12bab90e552d7aa81209ef (patch) | |
tree | 8b31f38de9882d18df54cf8d9e0de74167a094eb /includes/changes | |
parent | 15e69f7b20b6596b9148030acce5b59993b95a45 (diff) | |
parent | 257401d8b2cf661adf36c84b0e3fd1cf85e33c22 (diff) |
Merge branch 'mw-1.26'
Diffstat (limited to 'includes/changes')
-rw-r--r-- | includes/changes/ChangesFeed.php | 4 | ||||
-rw-r--r-- | includes/changes/ChangesList.php | 39 | ||||
-rw-r--r-- | includes/changes/EnhancedChangesList.php | 262 | ||||
-rw-r--r-- | includes/changes/RecentChange.php | 113 |
4 files changed, 296 insertions, 122 deletions
diff --git a/includes/changes/ChangesFeed.php b/includes/changes/ChangesFeed.php index 28c2f7ed..28a1ccad 100644 --- a/includes/changes/ChangesFeed.php +++ b/includes/changes/ChangesFeed.php @@ -187,6 +187,10 @@ class ChangesFeed { $sorted = array(); $n = 0; foreach ( $rows as $obj ) { + if ( $obj->rc_type == RC_EXTERNAL ) { + continue; + } + if ( $n > 0 && $obj->rc_type == RC_EDIT && $obj->rc_namespace >= 0 && diff --git a/includes/changes/ChangesList.php b/includes/changes/ChangesList.php index 932006d4..fdc9944f 100644 --- a/includes/changes/ChangesList.php +++ b/includes/changes/ChangesList.php @@ -204,7 +204,8 @@ class ChangesList extends ContextSource { $code = $lang->getCode(); static $fastCharDiff = array(); if ( !isset( $fastCharDiff[$code] ) ) { - $fastCharDiff[$code] = $config->get( 'MiserMode' ) || $context->msg( 'rc-change-size' )->plain() === '$1'; + $fastCharDiff[$code] = $config->get( 'MiserMode' ) + || $context->msg( 'rc-change-size' )->plain() === '$1'; } $formattedSize = $lang->formatNum( $szdiff ); @@ -371,6 +372,19 @@ class ChangesList extends ContextSource { } /** + * @param RecentChange $rc + * @param bool $unpatrolled + * @param bool $watched + * @return string + * @since 1.26 + */ + public function getArticleLink( RecentChange $rc, $unpatrolled, $watched ) { + $s = ''; + $this->insertArticleLink( $s, $rc, $unpatrolled, $watched ); + return $s; + } + + /** * Get the timestamp from $rc formatted with current user's settings * and a separator * @@ -543,6 +557,17 @@ class ChangesList extends ContextSource { } /** + * @param RecentChange $rc + * @return string + * @since 1.26 + */ + public function getRollback( RecentChange $rc ) { + $s = ''; + $this->insertRollback( $s, $rc ); + return $s; + } + + /** * @param string $s * @param RecentChange $rc * @param array $classes @@ -560,6 +585,18 @@ class ChangesList extends ContextSource { $s .= ' ' . $tagSummary; } + /** + * @param RecentChange $rc + * @param array $classes + * @return string + * @since 1.26 + */ + public function getTags( RecentChange $rc, array &$classes ) { + $s = ''; + $this->insertTags( $s, $rc, $classes ); + return $s; + } + public function insertExtra( &$s, &$rc, &$classes ) { // Empty, used for subclasses to add anything special. } diff --git a/includes/changes/EnhancedChangesList.php b/includes/changes/EnhancedChangesList.php index 19277f10..d912e3a2 100644 --- a/includes/changes/EnhancedChangesList.php +++ b/includes/changes/EnhancedChangesList.php @@ -270,6 +270,20 @@ class EnhancedChangesList extends ChangesList { $queryParams['curid'] = $curId; + # Sub-entries + $lines = ''; + foreach ( $block as $i => $rcObj ) { + $line = $this->getLineData( $block, $rcObj, $queryParams ); + $lines .= $line; + if ( !$line ) { + // completely ignore this RC entry if we don't want to render it + unset( $block[$i] ); + } + } + // Further down are some assumptions that $block is a 0-indexed array + // with (count-1) as last key. Let's make sure it is. + $block = array_values( $block ); + $r .= $this->getLogText( $block, $queryParams, $allLogs, $isnew, $namehidden ); $r .= ' <span class="mw-changeslist-separator">. .</span> '; @@ -299,88 +313,133 @@ class EnhancedChangesList extends ChangesList { $r .= $this->numberofWatchingusers( $block[0]->numberofWatchingusers ); $r .= '</td></tr>'; - # Sub-entries - foreach ( $block as $rcObj ) { - # Classes to apply -- TODO implement - $classes = array(); - $type = $rcObj->mAttribs['rc_type']; - - $trClass = $rcObj->watched && $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched - ? ' class="mw-enhanced-watched"' : ''; - - $r .= '<tr' . $trClass . '><td></td><td class="mw-enhanced-rc">'; - $r .= $this->recentChangesFlags( array( - 'newpage' => $type == RC_NEW, - 'minor' => $rcObj->mAttribs['rc_minor'], - 'unpatrolled' => $rcObj->unpatrolled, - 'bot' => $rcObj->mAttribs['rc_bot'], - ) ); - $r .= ' </td><td class="mw-enhanced-rc-nested"><span class="mw-enhanced-rc-time">'; + if ( !$lines ) { + // if there are no lines to be rendered (all aborted by hook), don't render the block + return ''; + } - $params = $queryParams; + $r .= $lines; + $r .= "</table>\n"; - if ( $rcObj->mAttribs['rc_this_oldid'] != 0 ) { - $params['oldid'] = $rcObj->mAttribs['rc_this_oldid']; - } + $this->rcCacheIndex++; - # Log timestamp - if ( $type == RC_LOG ) { - $link = $rcObj->timestamp; - # Revision link - } elseif ( !ChangesList::userCan( $rcObj, Revision::DELETED_TEXT, $this->getUser() ) ) { - $link = '<span class="history-deleted">' . $rcObj->timestamp . '</span> '; - } else { + return $r; + } - $link = Linker::linkKnown( - $rcObj->getTitle(), - $rcObj->timestamp, - array(), - $params - ); - if ( $this->isDeleted( $rcObj, Revision::DELETED_TEXT ) ) { - $link = '<span class="history-deleted">' . $link . '</span> '; - } + /** + * @param RCCacheEntry[] $block + * @param RCCacheEntry $rcObj + * @param array $queryParams + * @return string + * @throws Exception + * @throws FatalError + * @throws MWException + */ + protected function getLineData( array $block, RCCacheEntry $rcObj, array $queryParams = array() ) { + $RCShowChangedSize = $this->getConfig()->get( 'RCShowChangedSize' ); + + # Classes to apply -- TODO implement + $classes = array(); + $type = $rcObj->mAttribs['rc_type']; + $data = array(); + + $trClass = $rcObj->watched && $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched + ? ' class="mw-enhanced-watched"' : ''; + $separator = ' <span class="mw-changeslist-separator">. .</span> '; + + $data['recentChangesFlags'] = array( + 'newpage' => $type == RC_NEW, + 'minor' => $rcObj->mAttribs['rc_minor'], + 'unpatrolled' => $rcObj->unpatrolled, + 'bot' => $rcObj->mAttribs['rc_bot'], + ); + + $params = $queryParams; + + if ( $rcObj->mAttribs['rc_this_oldid'] != 0 ) { + $params['oldid'] = $rcObj->mAttribs['rc_this_oldid']; + } + + # Log timestamp + if ( $type == RC_LOG ) { + $link = $rcObj->timestamp; + # Revision link + } elseif ( !ChangesList::userCan( $rcObj, Revision::DELETED_TEXT, $this->getUser() ) ) { + $link = '<span class="history-deleted">' . $rcObj->timestamp . '</span> '; + } else { + $link = Linker::linkKnown( + $rcObj->getTitle(), + $rcObj->timestamp, + array(), + $params + ); + if ( $this->isDeleted( $rcObj, Revision::DELETED_TEXT ) ) { + $link = '<span class="history-deleted">' . $link . '</span> '; } - $r .= $link . '</span>'; + } + $data['timestampLink'] = $link; - if ( !$type == RC_LOG || $type == RC_NEW ) { - $r .= ' ' . $this->msg( 'parentheses' )->rawParams( + $currentAndLastLinks = ''; + if ( !$type == RC_LOG || $type == RC_NEW ) { + $currentAndLastLinks .= ' ' . $this->msg( 'parentheses' )->rawParams( $rcObj->curlink . - $this->message['pipe-separator'] . - $rcObj->lastlink + $this->message['pipe-separator'] . + $rcObj->lastlink )->escaped(); - } - $r .= ' <span class="mw-changeslist-separator">. .</span> '; + } + $data['currentAndLastLinks'] = $currentAndLastLinks; + $data['separatorAfterCurrentAndLastLinks'] = $separator; - # Character diff - if ( $RCShowChangedSize ) { - $cd = $this->formatCharacterDifference( $rcObj ); - if ( $cd !== '' ) { - $r .= $cd . ' <span class="mw-changeslist-separator">. .</span> '; - } + # Character diff + if ( $RCShowChangedSize ) { + $cd = $this->formatCharacterDifference( $rcObj ); + if ( $cd !== '' ) { + $data['characterDiff'] = $cd; + $data['separatorAfterCharacterDiff'] = $separator; } + } - if ( $rcObj->mAttribs['rc_type'] == RC_LOG ) { - $r .= $this->insertLogEntry( $rcObj ); - } else { - # User links - $r .= $rcObj->userlink; - $r .= $rcObj->usertalklink; - $r .= $this->insertComment( $rcObj ); - } + if ( $rcObj->mAttribs['rc_type'] == RC_LOG ) { + $data['logEntry'] = $this->insertLogEntry( $rcObj ); + } else { + # User links + $data['userLink'] = $rcObj->userlink; + $data['userTalkLink'] = $rcObj->usertalklink; + $data['comment'] = $this->insertComment( $rcObj ); + } + + # Rollback + $data['rollback'] = $this->getRollback( $rcObj ); - # Rollback - $this->insertRollback( $r, $rcObj ); - # Tags - $this->insertTags( $r, $rcObj, $classes ); + # Tags + $data['tags'] = $this->getTags( $rcObj, $classes ); - $r .= "</td></tr>\n"; + // give the hook a chance to modify the data + $success = Hooks::run( 'EnhancedChangesListModifyLineData', + array( $this, &$data, $block, $rcObj ) ); + if ( !$success ) { + // skip entry if hook aborted it + return ''; } - $r .= "</table>\n"; - $this->rcCacheIndex++; + $line = '<tr' . $trClass . '><td></td><td class="mw-enhanced-rc">'; + if ( isset( $data['recentChangesFlags'] ) ) { + $line .= $this->recentChangesFlags( $data['recentChangesFlags'] ); + unset( $data['recentChangesFlags'] ); + } + $line .= ' </td><td class="mw-enhanced-rc-nested">'; - return $r; + if ( isset( $data['timestampLink'] ) ) { + $line .= '<span class="mw-enhanced-rc-time">' . $data['timestampLink'] . '</span>'; + unset( $data['timestampLink'] ); + } + + // everything else: makes it easier for extensions to add or remove data + $line .= implode( '', $data ); + + $line .= "</td></tr>\n"; + + return $line; } /** @@ -498,6 +557,8 @@ class EnhancedChangesList extends ChangesList { * @return string A HTML formatted line (generated using $r) */ protected function recentChangesBlockLine( $rcObj ) { + $data = array(); + $query['curid'] = $rcObj->mAttribs['rc_cur_id']; $type = $rcObj->mAttribs['rc_type']; @@ -512,32 +573,33 @@ class EnhancedChangesList extends ChangesList { } $classes[] = $rcObj->watched && $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched'; - $r = Html::openElement( 'table', array( 'class' => $classes ) ) . - Html::openElement( 'tr' ); - $r .= '<td class="mw-enhanced-rc"><span class="mw-enhancedchanges-arrow-space"></span>'; # Flag and Timestamp - $r .= $this->recentChangesFlags( array( + $data['recentChangesFlags'] = array( 'newpage' => $type == RC_NEW, 'minor' => $rcObj->mAttribs['rc_minor'], 'unpatrolled' => $rcObj->unpatrolled, 'bot' => $rcObj->mAttribs['rc_bot'], - ) ); - $r .= ' ' . $rcObj->timestamp . ' </td><td>'; + ); + // timestamp is not really a link here, but is called timestampLink + // for consistency with EnhancedChangesListModifyLineData + $data['timestampLink'] = $rcObj->timestamp; + # Article or log link if ( $logType ) { $logPage = new LogPage( $logType ); $logTitle = SpecialPage::getTitleFor( 'Log', $logType ); $logName = $logPage->getName()->escaped(); - $r .= $this->msg( 'parentheses' ) + $data['logLink'] = $this->msg( 'parentheses' ) ->rawParams( Linker::linkKnown( $logTitle, $logName ) )->escaped(); } else { - $this->insertArticleLink( $r, $rcObj, $rcObj->unpatrolled, $rcObj->watched ); + $data['articleLink'] = $this->getArticleLink( $rcObj, $rcObj->unpatrolled, $rcObj->watched ); } + # Diff and hist links if ( $type != RC_LOG ) { $query['action'] = 'history'; - $r .= ' ' . $this->msg( 'parentheses' ) + $data['historyLink'] = ' ' . $this->msg( 'parentheses' ) ->rawParams( $rcObj->difflink . $this->message['pipe-separator'] . Linker::linkKnown( $rcObj->getTitle(), $this->message['hist'], @@ -545,31 +607,61 @@ class EnhancedChangesList extends ChangesList { $query ) )->escaped(); } - $r .= ' <span class="mw-changeslist-separator">. .</span> '; + $data['separatorAfterLinks'] = ' <span class="mw-changeslist-separator">. .</span> '; + # Character diff if ( $this->getConfig()->get( 'RCShowChangedSize' ) ) { $cd = $this->formatCharacterDifference( $rcObj ); if ( $cd !== '' ) { - $r .= $cd . ' <span class="mw-changeslist-separator">. .</span> '; + $data['characterDiff'] = $cd; + $data['separatorAftercharacterDiff'] = ' <span class="mw-changeslist-separator">. .</span> '; } } if ( $type == RC_LOG ) { - $r .= $this->insertLogEntry( $rcObj ); + $data['logEntry'] = $this->insertLogEntry( $rcObj ); } else { - $r .= ' ' . $rcObj->userlink . $rcObj->usertalklink; - $r .= $this->insertComment( $rcObj ); - $this->insertRollback( $r, $rcObj ); + $data['userLink'] = $rcObj->userlink; + $data['userTalkLink'] = $rcObj->usertalklink; + $data['comment'] = $this->insertComment( $rcObj ); + $data['rollback'] = $this->getRollback( $rcObj ); } # Tags - $this->insertTags( $r, $rcObj, $classes ); + $data['tags'] = $this->getTags( $rcObj, $classes ); + # Show how many people are watching this if enabled - $r .= $this->numberofWatchingusers( $rcObj->numberofWatchingusers ); + $data['watchingUsers'] = $this->numberofWatchingusers( $rcObj->numberofWatchingusers ); - $r .= "</td></tr></table>\n"; + // give the hook a chance to modify the data + $success = Hooks::run( 'EnhancedChangesListModifyBlockLineData', + array( $this, &$data, $rcObj ) ); + if ( !$success ) { + // skip entry if hook aborted it + return ''; + } - return $r; + $line = Html::openElement( 'table', array( 'class' => $classes ) ) . + Html::openElement( 'tr' ); + $line .= '<td class="mw-enhanced-rc"><span class="mw-enhancedchanges-arrow-space"></span>'; + + if ( isset( $data['recentChangesFlags'] ) ) { + $line .= $this->recentChangesFlags( $data['recentChangesFlags'] ); + unset( $data['recentChangesFlags'] ); + } + + if ( isset( $data['timestampLink'] ) ) { + $line .= ' ' . $data['timestampLink']; + unset( $data['timestampLink'] ); + } + $line .= ' </td><td>'; + + // everything else: makes it easier for extensions to add or remove data + $line .= implode( '', $data ); + + $line .= "</td></tr></table>\n"; + + return $line; } /** diff --git a/includes/changes/RecentChange.php b/includes/changes/RecentChange.php index b430bab9..87871f49 100644 --- a/includes/changes/RecentChange.php +++ b/includes/changes/RecentChange.php @@ -89,6 +89,16 @@ class RecentChange { */ public $counter = -1; + /** + * @var array Array of change types + */ + private static $changeTypes = array( + 'edit' => RC_EDIT, + 'new' => RC_NEW, + 'log' => RC_LOG, + 'external' => RC_EXTERNAL, + ); + # Factory methods /** @@ -119,18 +129,10 @@ class RecentChange { return $retval; } - switch ( $type ) { - case 'edit': - return RC_EDIT; - case 'new': - return RC_NEW; - case 'log': - return RC_LOG; - case 'external': - return RC_EXTERNAL; - default: - throw new MWException( "Unknown type '$type'" ); + if ( !array_key_exists( $type, self::$changeTypes ) ) { + throw new MWException( "Unknown type '$type'" ); } + return self::$changeTypes[$type]; } /** @@ -140,31 +142,25 @@ class RecentChange { * @return string $type */ public static function parseFromRCType( $rcType ) { - switch ( $rcType ) { - case RC_EDIT: - $type = 'edit'; - break; - case RC_NEW: - $type = 'new'; - break; - case RC_LOG: - $type = 'log'; - break; - case RC_EXTERNAL: - $type = 'external'; - break; - default: - $type = "$rcType"; - } + return array_search( $rcType, self::$changeTypes, true ) ?: "$rcType"; + } - return $type; + /** + * Get an array of all change types + * + * @since 1.26 + * + * @return array + */ + public static function getChangeTypes() { + return array_keys( self::$changeTypes ); } /** * Obtain the recent change with a given rc_id value * * @param int $rcid The rc_id value to retrieve - * @return RecentChange + * @return RecentChange|null */ public static function newFromId( $rcid ) { return self::newFromConds( array( 'rc_id' => $rcid ), __METHOD__ ); @@ -176,7 +172,7 @@ class RecentChange { * @param array $conds Array of conditions * @param mixed $fname Override the method name in profiling/logs * @param array $options Query options - * @return RecentChange + * @return RecentChange|null */ public static function newFromConds( $conds, $fname = __METHOD__, $options = array() ) { $dbr = wfGetDB( DB_SLAVE ); @@ -332,6 +328,11 @@ class RecentChange { $this->mExtra['pageStatus'] ); } } + + // Update the cached list of active users + if ( $this->mAttribs['rc_user'] > 0 ) { + JobQueueGroup::singleton()->lazyPush( RecentChangesUpdateJob::newCacheUpdateJob() ); + } } /** @@ -377,6 +378,13 @@ class RecentChange { /** @var $formatter RCFeedFormatter */ $formatter = is_object( $feed['formatter'] ) ? $feed['formatter'] : new $feed['formatter'](); $line = $formatter->getLine( $feed, $this, $actionComment ); + if ( !$line ) { + // T109544 + // If a feed formatter returns null, this will otherwise cause an + // error in at least RedisPubSubFeedEngine. + // Not sure where/how this should best be handled. + continue; + } $engine->send( $feed, $line ); } @@ -512,8 +520,10 @@ class RecentChange { * @param int $patrol * @return RecentChange */ - public static function notifyEdit( $timestamp, &$title, $minor, &$user, $comment, $oldId, - $lastTimestamp, $bot, $ip = '', $oldSize = 0, $newSize = 0, $newId = 0, $patrol = 0 ) { + public static function notifyEdit( + $timestamp, &$title, $minor, &$user, $comment, $oldId, $lastTimestamp, + $bot, $ip = '', $oldSize = 0, $newSize = 0, $newId = 0, $patrol = 0 + ) { $rc = new RecentChange; $rc->mTitle = $title; $rc->mPerformer = $user; @@ -550,7 +560,13 @@ class RecentChange { 'newSize' => $newSize, 'pageStatus' => 'changed' ); - $rc->save(); + + DeferredUpdates::addCallableUpdate( function() use ( $rc ) { + $rc->save(); + if ( $rc->mAttribs['rc_patrolled'] ) { + PatrolLog::record( $rc, true, $rc->getPerformer() ); + } + } ); return $rc; } @@ -571,8 +587,10 @@ class RecentChange { * @param int $patrol * @return RecentChange */ - public static function notifyNew( $timestamp, &$title, $minor, &$user, $comment, $bot, - $ip = '', $size = 0, $newId = 0, $patrol = 0 ) { + public static function notifyNew( + $timestamp, &$title, $minor, &$user, $comment, $bot, + $ip = '', $size = 0, $newId = 0, $patrol = 0 + ) { $rc = new RecentChange; $rc->mTitle = $title; $rc->mPerformer = $user; @@ -609,7 +627,13 @@ class RecentChange { 'newSize' => $size, 'pageStatus' => 'created' ); - $rc->save(); + + DeferredUpdates::addCallableUpdate( function() use ( $rc ) { + $rc->save(); + if ( $rc->mAttribs['rc_patrolled'] ) { + PatrolLog::record( $rc, true, $rc->getPerformer() ); + } + } ); return $rc; } @@ -827,4 +851,21 @@ class RecentChange { return wfTimestamp( TS_UNIX, $timestamp ) > time() - $tolerance - $wgRCMaxAge; } + + /** + * Parses and returns the rc_params attribute + * + * @since 1.26 + * + * @return array|null + */ + public function parseParams() { + $rcParams = $this->getAttribute( 'rc_params' ); + + MediaWiki\suppressWarnings(); + $unserializedParams = unserialize( $rcParams ); + MediaWiki\restoreWarnings(); + + return $unserializedParams; + } } |