Merge "WLFilters: fix server-side tag filtering"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 31 Aug 2017 18:27:57 +0000 (18:27 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 31 Aug 2017 18:27:57 +0000 (18:27 +0000)
1  2 
includes/specials/SpecialWatchlist.php

@@@ -104,10 -104,6 +104,10 @@@ class SpecialWatchlist extends ChangesL
                                'wgStructuredChangeFiltersSavedQueriesPreferenceName',
                                'rcfilters-wl-saved-queries'
                        );
 +                      $output->addJsConfigVars(
 +                              'wgStructuredChangeFiltersEditWatchlistUrl',
 +                              SpecialPage::getTitleFor( 'EditWatchlist' )->getLocalURL()
 +                      );
                }
        }
  
                $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' => [
                        ], 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 );
                        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,
                $showUpdatedMarker = $this->getConfig()->get( 'ShowUpdatedMarker' );
  
                // Show watchlist header
 -              $form .= "<p>";
 +              $watchlistHeader = '';
                if ( $numItems == 0 ) {
 -                      $form .= $this->msg( 'nowatchlist' )->parse() . "\n";
 +                      $watchlistHeader = $this->msg( 'nowatchlist' )->parse();
                } else {
 -                      $form .= $this->msg( 'watchlist-details' )->numParams( $numItems )->parse() . "\n";
 +                      $watchlistHeader .= $this->msg( 'watchlist-details' )->numParams( $numItems )->parse() . "\n";
                        if ( $this->getConfig()->get( 'EnotifWatchlist' )
                                && $user->getOption( 'enotifwatchlistpages' )
                        ) {
 -                              $form .= $this->msg( 'wlheader-enotif' )->parse() . "\n";
 +                              $watchlistHeader .= $this->msg( 'wlheader-enotif' )->parse() . "\n";
                        }
                        if ( $showUpdatedMarker ) {
 -                              $form .= $this->msg( 'wlheader-showupdated' )->parse() . "\n";
 +                              $watchlistHeader .= $this->msg(
 +                                      $this->isStructuredFilterUiEnabled() ?
 +                                              'rcfilters-watchlist-showupdated' :
 +                                              'wlheader-showupdated'
 +                              )->parse() . "\n";
                        }
                }
 -              $form .= "</p>";
 +              $form .= Html::rawElement(
 +                      'div',
 +                      [ 'class' => 'watchlistDetails' ],
 +                      $watchlistHeader
 +              );
  
                if ( $numItems > 0 && $showUpdatedMarker ) {
                        $form .= Xml::openElement( 'form', [ 'method' => 'post',