Merge "resourceloader: Support isKnownEmpty for general modules"
[lhc/web/wiklou.git] / includes / specials / SpecialWatchlist.php
index dcd2ffa..4f4570e 100644 (file)
@@ -32,6 +32,8 @@ use Wikimedia\Rdbms\IDatabase;
  * @ingroup SpecialPage
  */
 class SpecialWatchlist extends ChangesListSpecialPage {
+       protected static $savedQueriesPreferenceName = 'rcfilters-wl-saved-queries';
+
        private $maxDays;
 
        public function __construct( $page = 'Watchlist', $restriction = 'viewmywatchlist' ) {
@@ -100,10 +102,6 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        $output->addModuleStyles( [ 'mediawiki.rcfilters.highlightCircles.seenunseen.styles' ] );
 
                        $output->addJsConfigVars( 'wgStructuredChangeFiltersLiveUpdateSupported', false );
-                       $output->addJsConfigVars(
-                               'wgStructuredChangeFiltersSavedQueriesPreferenceName',
-                               'rcfilters-wl-saved-queries'
-                       );
                        $output->addJsConfigVars(
                                'wgStructuredChangeFiltersEditWatchlistUrl',
                                SpecialPage::getTitleFor( 'EditWatchlist' )->getLocalURL()
@@ -111,10 +109,16 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                }
        }
 
-       protected function isStructuredFilterUiEnabled() {
-               return parent::isStructuredFilterUiEnabled()
-                       && ( $this->getConfig()->get( 'StructuredChangeFiltersOnWatchlist' )
-                               || $this->getRequest()->getBool( 'rcfilters' ) );
+       public function isStructuredFilterUiEnabled() {
+               return $this->getRequest()->getBool( 'rcfilters' ) || (
+                       $this->getConfig()->get( 'StructuredChangeFiltersOnWatchlist' ) &&
+                       $this->getUser()->getOption( 'rcenhancedfilters' )
+               );
+       }
+
+       public function isStructuredFilterUiEnabledByDefault() {
+               return $this->getConfig()->get( 'StructuredChangeFiltersOnWatchlist' ) &&
+                       $this->getUser()->getDefaultOption( 'rcenhancedfilters' );
        }
 
        /**
@@ -271,10 +275,9 @@ class SpecialWatchlist extends ChangesListSpecialPage {
         */
        public function getDefaultOptions() {
                $opts = parent::getDefaultOptions();
-               $user = $this->getUser();
 
-               $opts->add( 'days', $user->getOption( 'watchlistdays' ), FormOptions::FLOAT );
-               $opts->add( 'limit', $user->getIntOption( 'wllimit' ), FormOptions::INT );
+               $opts->add( 'days', $this->getDefaultDays(), FormOptions::FLOAT );
+               $opts->add( 'limit', $this->getDefaultLimit(), FormOptions::INT );
 
                return $opts;
        }
@@ -386,10 +389,6 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                $tables = array_merge( [ 'recentchanges', 'watchlist' ], $tables );
                $fields = array_merge( RecentChange::selectFields(), $fields );
 
-               $query_options = array_merge( [
-                       'ORDER BY' => 'rc_timestamp DESC',
-                       'LIMIT' => $opts['limit']
-               ], $query_options );
                $join_conds = array_merge(
                        [
                                'watchlist' => [
@@ -426,13 +425,14 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        ], LIST_OR );
                }
 
+               $tagFilter = $opts['tagfilter'] ? explode( '|', $opts['tagfilter'] ) : [];
                ChangeTags::modifyDisplayQuery(
                        $tables,
                        $fields,
                        $conds,
                        $join_conds,
                        $query_options,
-                       ''
+                       $tagFilter
                );
 
                $this->runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds, $opts );
@@ -441,6 +441,23 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        return false;
                }
 
+               $orderByAndLimit = [
+                       'ORDER BY' => 'rc_timestamp DESC',
+                       'LIMIT' => $opts['limit']
+               ];
+               if ( in_array( 'DISTINCT', $query_options ) ) {
+                       // ChangeTags::modifyDisplayQuery() adds DISTINCT when filtering on multiple tags.
+                       // In order to prevent DISTINCT from causing query performance problems,
+                       // we have to GROUP BY the primary key. This in turn requires us to add
+                       // the primary key to the end of the ORDER BY, and the old ORDER BY to the
+                       // start of the GROUP BY
+                       $orderByAndLimit['ORDER BY'] = 'rc_timestamp DESC, rc_id DESC';
+                       $orderByAndLimit['GROUP BY'] = 'rc_timestamp, rc_id';
+               }
+               // array_merge() is used intentionally here so that hooks can, should
+               // they so desire, override the ORDER BY / LIMIT condition(s)
+               $query_options = array_merge( $orderByAndLimit, $query_options );
+
                return $dbr->select(
                        $tables,
                        $fields,
@@ -616,11 +633,13 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        'id' => 'mw-watchlist-form'
                ] );
                $form .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() );
-               $form .= Xml::fieldset(
-                       $this->msg( 'watchlist-options' )->text(),
-                       false,
+               $form .= Xml::openElement(
+                       'fieldset',
                        [ 'id' => 'mw-watchlist-options', 'class' => 'cloptions' ]
                );
+               $form .= Xml::element(
+                       'legend', null, $this->msg( 'watchlist-options' )->text()
+               );
 
                if ( !$this->isStructuredFilterUiEnabled() ) {
                        $form .= $this->makeLegend();
@@ -830,11 +849,15 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                                $watchlistHeader .= $this->msg( 'wlheader-enotif' )->parse() . "\n";
                        }
                        if ( $showUpdatedMarker ) {
-                               $watchlistHeader .= $this->msg( 'wlheader-showupdated' )->parse() . "\n";
+                               $watchlistHeader .= $this->msg(
+                                       $this->isStructuredFilterUiEnabled() ?
+                                               'rcfilters-watchlist-showupdated' :
+                                               'wlheader-showupdated'
+                               )->parse() . "\n";
                        }
                }
                $form .= Html::rawElement(
-                       'p',
+                       'div',
                        [ 'class' => 'watchlistDetails' ],
                        $watchlistHeader
                );
@@ -894,6 +917,6 @@ class SpecialWatchlist extends ChangesListSpecialPage {
        }
 
        function getDefaultDays() {
-               return $this->getUser()->getIntOption( 'watchlistdays' );
+               return floatval( $this->getUser()->getOption( 'watchlistdays' ) );
        }
 }