* @ingroup SpecialPage
*/
class SpecialRecentChanges extends ChangesListSpecialPage {
+
+ private $watchlistFilterGroupDefinition;
+
// @codingStandardsIgnoreStart Needed "useless" override to change parameters.
public function __construct( $name = 'Recentchanges', $restriction = '' ) {
parent::__construct( $name, $restriction );
+
+ $this->watchlistFilterGroupDefinition = [
+ 'name' => 'watchlist',
+ 'title' => 'rcfilters-filtergroup-watchlist',
+ 'class' => ChangesListStringOptionsFilterGroup::class,
+ 'priority' => -9,
+ 'isFullCoverage' => true,
+ 'filters' => [
+ [
+ 'name' => 'watched',
+ 'label' => 'rcfilters-filter-watchlist-watched-label',
+ 'description' => 'rcfilters-filter-watchlist-watched-description',
+ 'cssClassSuffix' => 'watched',
+ 'isRowApplicableCallable' => function ( $ctx, $rc ) {
+ return $rc->getAttribute( 'wl_user' );
+ }
+ ],
+ [
+ 'name' => 'watchednew',
+ 'label' => 'rcfilters-filter-watchlist-watchednew-label',
+ 'description' => 'rcfilters-filter-watchlist-watchednew-description',
+ 'cssClassSuffix' => 'watchednew',
+ 'isRowApplicableCallable' => function ( $ctx, $rc ) {
+ return $rc->getAttribute( 'wl_user' ) &&
+ $rc->getAttribute( 'rc_timestamp' ) &&
+ $rc->getAttribute( 'wl_notificationtimestamp' ) &&
+ $rc->getAttribute( 'rc_timestamp' ) >= $rc->getAttribute( 'wl_notificationtimestamp' );
+ },
+ ],
+ [
+ 'name' => 'notwatched',
+ 'label' => 'rcfilters-filter-watchlist-notwatched-label',
+ 'description' => 'rcfilters-filter-watchlist-notwatched-description',
+ 'cssClassSuffix' => 'notwatched',
+ 'isRowApplicableCallable' => function ( $ctx, $rc ) {
+ return $rc->getAttribute( 'wl_user' ) === null;
+ },
+ ]
+ ],
+ 'default' => ChangesListStringOptionsFilterGroup::NONE,
+ 'queryCallable' => function ( $specialPageClassName, $context, $dbr,
+ &$tables, &$fields, &$conds, &$query_options, &$join_conds, $selectedValues ) {
+ sort( $selectedValues );
+ $notwatchedCond = 'wl_user IS NULL';
+ $watchedCond = 'wl_user IS NOT NULL';
+ $newCond = 'rc_timestamp >= wl_notificationtimestamp';
+
+ if ( $selectedValues === [ 'notwatched' ] ) {
+ $conds[] = $notwatchedCond;
+ return;
+ }
+
+ if ( $selectedValues === [ 'watched' ] ) {
+ $conds[] = $watchedCond;
+ return;
+ }
+
+ if ( $selectedValues === [ 'watchednew' ] ) {
+ $conds[] = $dbr->makeList( [
+ $watchedCond,
+ $newCond
+ ], LIST_AND );
+ return;
+ }
+
+ if ( $selectedValues === [ 'notwatched', 'watched' ] ) {
+ // no filters
+ return;
+ }
+
+ if ( $selectedValues === [ 'notwatched', 'watchednew' ] ) {
+ $conds[] = $dbr->makeList( [
+ $notwatchedCond,
+ $dbr->makeList( [
+ $watchedCond,
+ $newCond
+ ], LIST_AND )
+ ], LIST_OR );
+ return;
+ }
+
+ if ( $selectedValues === [ 'watched', 'watchednew' ] ) {
+ $conds[] = $watchedCond;
+ return;
+ }
+
+ if ( $selectedValues === [ 'notwatched', 'watched', 'watchednew' ] ) {
+ // no filters
+ return;
+ }
+ }
+ ];
}
// @codingStandardsIgnoreEnd
$jsData = $this->getStructuredFilterJsData();
$messages = [];
- foreach ( $jsData['messageKeys'] as $key ){
+ foreach ( $jsData['messageKeys'] as $key ) {
$messages[$key] = $this->msg( $key )->plain();
}
protected function registerFilters() {
parent::registerFilters();
+ if (
+ !$this->including() &&
+ $this->getUser()->isLoggedIn() &&
+ $this->getUser()->isAllowed( 'viewmywatchlist' )
+ ) {
+ $this->registerFiltersFromDefinitions( [ $this->watchlistFilterGroupDefinition ] );
+ $watchlistGroup = $this->getFilterGroup( 'watchlist' );
+ $watchlistGroup->getFilter( 'watched' )->setAsSupersetOf(
+ $watchlistGroup->getFilter( 'watchednew' )
+ );
+ }
+
$user = $this->getUser();
$significance = $this->getFilterGroup( 'significance' );
$fields = array_merge( RecentChange::selectFields(), $fields );
// JOIN on watchlist for users
- if ( $user->getId() && $user->isAllowed( 'viewmywatchlist' ) ) {
+ if ( $user->isLoggedIn() && $user->isAllowed( 'viewmywatchlist' ) ) {
$tables[] = 'watchlist';
$fields[] = 'wl_user';
$fields[] = 'wl_notificationtimestamp';
] ];
}
- if ( $user->isAllowed( 'rollback' ) ) {
- $tables[] = 'page';
- $fields[] = 'page_latest';
- $join_conds['page'] = [ 'LEFT JOIN', 'rc_cur_id=page_id' ];
- }
+ // JOIN on page, used for 'last revision' filter highlight
+ $tables[] = 'page';
+ $fields[] = 'page_latest';
+ $join_conds['page'] = [ 'LEFT JOIN', 'rc_cur_id=page_id' ];
ChangeTags::modifyDisplayQuery(
$tables,
return false;
}
+ if ( $this->areFiltersInConflict() ) {
+ return false;
+ }
+
// array_merge() is used intentionally here so that hooks can, should
// they so desire, override the ORDER BY / LIMIT condition(s); prior to
// MediaWiki 1.26 this used to use the plus operator instead, which meant
* @return string
*/
function makeOptionsLink( $title, $override, $options, $active = false ) {
- $params = $override + $options;
-
- // T38524: false values have be converted to "0" otherwise
- // wfArrayToCgi() will omit it them.
- foreach ( $params as &$value ) {
- if ( $value === false ) {
- $value = '0';
- }
- }
- unset( $value );
+ $params = $this->convertParamsForLink( $override + $options );
if ( $active ) {
$title = new HtmlArmor( '<strong>' . htmlspecialchars( $title ) . '</strong>' );
$datenow = $lang->userDate( $timestamp, $user );
$pipedLinks = '<span class="rcshowhide">' . $lang->pipeList( $links ) . '</span>';
- $rclinks = '<span class="rclinks">' . $this->msg( 'rclinks' )->rawParams( $cl, $dl, $pipedLinks )
+ $rclinks = '<span class="rclinks">' . $this->msg( 'rclinks' )->rawParams( $cl, $dl, '' )
->parse() . '</span>';
$rclistfrom = '<span class="rclistfrom">' . $this->makeOptionsLink(
$nondefaults
) . '</span>';
- return "{$note}$rclinks<br />$rclistfrom";
+ return "{$note}$rclinks<br />$pipedLinks<br />$rclistfrom";
}
public function isIncludable() {