$opts->add( 'limit', (int)$wgUser->getOption( 'rclimit' ) );
$opts->add( 'from', '' );
- $opts->add( 'hideminor', (bool)$wgUser->getOption( 'hideminor' ) );
+ $opts->add( 'hideminor', $wgUser->getBoolOption( 'hideminor' ) );
$opts->add( 'hidebots', true );
$opts->add( 'hideanons', false );
$opts->add( 'hideliu', false );
- $opts->add( 'hidepatrolled', false );
+ $opts->add( 'hidepatrolled', $wgUser->getBoolOption( 'hidepatrolled' ) );
$opts->add( 'hidemyself', false );
$opts->add( 'namespace', '', FormOptions::INTNULL );
$opts->add( 'categories', '' );
$opts->add( 'categories_any', false );
+ $opts->add( 'tagfilter', '' );
return $opts;
}
$this->parseParameters( $parameters, $opts );
}
- $opts->validateIntBounds( 'limit', 0, 5000 );
+ $opts->validateIntBounds( 'limit', 0, 500 );
return $opts;
}
public function feedSetup() {
global $wgFeedLimit, $wgRequest;
$opts = $this->getDefaultOptions();
- $opts->fetchValuesFromRequest( $wgRequest, array( 'days', 'limit', 'hideminor' ) );
+ # Feed is cached on limit,hideminor; other params would randomly not work
+ $opts->fetchValuesFromRequest( $wgRequest, array( 'limit', 'hideminor' ) );
$opts->validateIntBounds( 'limit', 0, $wgFeedLimit );
return $opts;
}
foreach( $rows as $row ) {
$batch->add( NS_USER, $row->rc_user_text );
$batch->add( NS_USER_TALK, $row->rc_user_text );
+ $batch->add( $row->rc_namespace, $row->rc_title );
}
$batch->execute();
}
-
+ $target = isset($opts['target']) ? $opts['target'] : ''; // RCL has targets
if( $feedFormat ) {
list( $feed, $feedObj ) = $this->getFeedObject( $feedFormat );
- $feed->execute( $feedObj, $rows, $opts['limit'], $opts['hideminor'], $lastmod );
+ $feed->execute( $feedObj, $rows, $opts['limit'], $opts['hideminor'], $lastmod, $target );
} else {
$this->webOutput( $rows, $opts );
}
public function checkLastModified( $feedFormat ) {
global $wgUseRCPatrol, $wgOut;
$dbr = wfGetDB( DB_SLAVE );
- $lastmod = $dbr->selectField( 'recentchanges', 'MAX(rc_timestamp)', false, __FUNCTION__ );
+ $lastmod = $dbr->selectField( 'recentchanges', 'MAX(rc_timestamp)', false, __METHOD__ );
if( $feedFormat || !$wgUseRCPatrol ) {
if( $lastmod && $wgOut->checkLastModified( $lastmod ) ) {
# Client cache fresh and headers sent, nothing more to do.
$tables = array( 'recentchanges' );
$join_conds = array();
+ $query_options = array( 'USE INDEX' => array('recentchanges' => 'rc_timestamp') );
$uid = $wgUser->getId();
$dbr = wfGetDB( DB_SLAVE );
$namespace = $opts['namespace'];
$invert = $opts['invert'];
+ $join_conds = array();
+
// JOIN on watchlist for users
if( $uid ) {
$tables[] = 'watchlist';
- $join_conds = array( 'watchlist' => array('LEFT JOIN',
- "wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace") );
+ $join_conds['watchlist'] = array('LEFT JOIN',
+ "wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace");
}
+ if ($wgUser->isAllowed("rollback")) {
+ $tables[] = 'page';
+ $join_conds['page'] = array('LEFT JOIN', 'rc_cur_id=page_id');
+ }
+ // Tag stuff.
+ $fields = array();
+ // Fields are * in this case, so let the function modify an empty array to keep it happy.
+ ChangeTags::modifyDisplayQuery( $tables,
+ $fields,
+ $conds,
+ $join_conds,
+ $query_options,
+ $opts['tagfilter']
+ );
wfRunHooks('SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts ) );
// Is there either one namespace selected or excluded?
+ // Tag filtering also has a better index.
// Also, if this is "all" or main namespace, just use timestamp index.
- if( is_null($namespace) || $invert || $namespace == NS_MAIN ) {
+ if( is_null($namespace) || $invert || $opts['tagfilter'] ) {
$res = $dbr->select( $tables, '*', $conds, __METHOD__,
- array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit,
- 'USE INDEX' => array('recentchanges' => 'rc_timestamp') ),
+ array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit ) +
+ $query_options,
$join_conds );
// We have a new_namespace_time index! UNION over new=(0,1) and sort result set!
} else {
array( 'rc_new' => 1 ) + $conds,
__METHOD__,
array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit,
- 'USE INDEX' => array('recentchanges' => 'new_name_timestamp') ),
+ 'USE INDEX' => array('recentchanges' => 'rc_timestamp') ),
$join_conds );
// Old pages
$sqlOld = $dbr->selectSQLText( $tables, '*',
array( 'rc_new' => 0 ) + $conds,
__METHOD__,
array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit,
- 'USE INDEX' => array('recentchanges' => 'new_name_timestamp') ),
+ 'USE INDEX' => array('recentchanges' => 'rc_timestamp') ),
$join_conds );
# Join the two fast queries, and sort the result set
- $sql = "($sqlNew) UNION ($sqlOld) ORDER BY rc_timestamp DESC LIMIT $limit";
+ $sql = $dbr->unionQueries(array($sqlNew, $sqlOld), false).' ORDER BY rc_timestamp DESC';
+ $sql = $dbr->limitResult($sql, $limit, false);
$res = $dbr->query( $sql, __METHOD__ );
}
}
$rc->numberofWatchingusers = $watcherCache[$obj->rc_namespace][$obj->rc_title];
}
- $s .= $list->recentChangesLine( $rc, !empty( $obj->wl_user ) );
+ $s .= $list->recentChangesLine( $rc, !empty( $obj->wl_user ), $counter );
--$limit;
}
$s .= $list->endRecentChangesList();
$extraOpts['category'] = $this->categoryFilterForm( $opts );
}
+ $tagFilter = ChangeTags::buildTagFilterSelector( $opts['tagfilter'] );
+ if ( count($tagFilter) )
+ $extraOpts['tagfilter'] = $tagFilter;
+
wfRunHooks( 'SpecialRecentChangesPanel', array( &$extraOpts, $opts ) );
return $extraOpts;
}
global $wgUser;
$sk = $wgUser->getSkin();
$params = $override + $options;
- return $sk->link( $this->getTitle(), htmlspecialchars( $title ),
- ( $active ? array( 'style'=>'font-weight: bold;' ) : array() ), $params, array( 'known' ) );
+ if ( $active ) {
+ return $sk->link( $this->getTitle(), '<strong>' . htmlspecialchars( $title ) . '</strong>',
+ array(), $params, array( 'known' ) );
+ } else {
+ return $sk->link( $this->getTitle(), htmlspecialchars( $title ), array() , $params, array( 'known' ) );
+ }
}
/**
$options = $nondefaults + $defaults;
$note = '';
+ if( !wfEmptyMsg( 'rclegend', wfMsg('rclegend') ) ) {
+ $note .= '<div class="mw-rclegend">' . wfMsgExt( 'rclegend', array('parseinline') ) . "</div>\n";
+ }
if( $options['from'] ) {
$note .= wfMsgExt( 'rcnotefrom', array( 'parseinline' ),
$wgLang->formatNum( $options['limit'] ),
- $wgLang->timeanddate( $options['from'], true ) ) . '<br />';
- }
- if( !wfEmptyMsg( 'rclegend', wfMsg('rclegend') ) ) {
- $note .= wfMsgExt( 'rclegend', array('parseinline') ) . '<br />';
+ $wgLang->timeanddate( $options['from'], true ),
+ $wgLang->date( $options['from'], true ),
+ $wgLang->time( $options['from'], true ) ) . '<br />';
}
# Sort data for display and make sure it's unique after we've added user data.
$cl[] = $this->makeOptionsLink( $wgLang->formatNum( $value ),
array( 'limit' => $value ), $nondefaults, $value == $options['limit'] ) ;
}
- $cl = implode( ' | ', $cl );
+ $cl = $wgLang->pipeList( $cl );
// day links, reset 'from' to none
foreach( $wgRCLinkDays as $value ) {
$dl[] = $this->makeOptionsLink( $wgLang->formatNum( $value ),
array( 'days' => $value, 'from' => '' ), $nondefaults, $value == $options['days'] ) ;
}
- $dl = implode( ' | ', $dl );
+ $dl = $wgLang->pipeList( $dl );
// show/hide links
if( $wgUser->useRCPatrol() )
$links[] = wfMsgHtml( 'rcshowhidepatr', $patrLink );
$links[] = wfMsgHtml( 'rcshowhidemine', $myselfLink );
- $hl = implode( ' | ', $links );
+ $hl = $wgLang->pipeList( $links );
// show from this onward link
$now = $wgLang->timeanddate( wfTimestampNow(), true );