summaryrefslogtreecommitdiff
path: root/includes/changes
diff options
context:
space:
mode:
authorPierre Schmitz <pierre@archlinux.de>2015-12-20 09:00:55 +0100
committerPierre Schmitz <pierre@archlinux.de>2015-12-20 09:00:55 +0100
commita2190ac74dd4d7080b12bab90e552d7aa81209ef (patch)
tree8b31f38de9882d18df54cf8d9e0de74167a094eb /includes/changes
parent15e69f7b20b6596b9148030acce5b59993b95a45 (diff)
parent257401d8b2cf661adf36c84b0e3fd1cf85e33c22 (diff)
Merge branch 'mw-1.26'
Diffstat (limited to 'includes/changes')
-rw-r--r--includes/changes/ChangesFeed.php4
-rw-r--r--includes/changes/ChangesList.php39
-rw-r--r--includes/changes/EnhancedChangesList.php262
-rw-r--r--includes/changes/RecentChange.php113
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 .= '&#160;</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 .= '&#160;</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 .= '&#160;' . $rcObj->timestamp . '&#160;</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 .= '&#160;' . $data['timestampLink'];
+ unset( $data['timestampLink'] );
+ }
+ $line .= '&#160;</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;
+ }
}