RCFilters: Filter duplicates when filtering for multiple tags
[lhc/web/wiklou.git] / includes / specials / SpecialRecentchanges.php
index 5ec2064..45235aa 100644 (file)
@@ -139,7 +139,8 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
         */
        public function execute( $subpage ) {
                global $wgStructuredChangeFiltersEnableSaving,
-                       $wgStructuredChangeFiltersEnableExperimentalViews;
+                       $wgStructuredChangeFiltersEnableExperimentalViews,
+                       $wgStructuredChangeFiltersEnableLiveUpdate;
 
                // Backwards-compatibility: redirect to new feed URLs
                $feedFormat = $this->getRequest()->getVal( 'feed' );
@@ -189,6 +190,10 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                                'wgStructuredChangeFiltersEnableExperimentalViews',
                                $wgStructuredChangeFiltersEnableExperimentalViews
                        );
+                       $out->addJsConfigVars(
+                               'wgStructuredChangeFiltersEnableLiveUpdate',
+                               $wgStructuredChangeFiltersEnableLiveUpdate
+                       );
                        $out->addJsConfigVars(
                                'wgRCFiltersChangeTags',
                                $this->buildChangeTagList()
@@ -213,7 +218,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags, $tagStats );
 
                // Sort by hits
-               asort( $tagHitCounts );
+               arsort( $tagHitCounts );
 
                // Build the list and data
                $result = [];
@@ -367,8 +372,8 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
         * @inheritdoc
         */
        protected function buildQuery( &$tables, &$fields, &$conds,
-               &$query_options, &$join_conds, FormOptions $opts ) {
-
+               &$query_options, &$join_conds, FormOptions $opts
+       ) {
                $dbr = $this->getDB();
                parent::buildQuery( $tables, $fields, $conds,
                        $query_options, $join_conds, $opts );
@@ -392,8 +397,8 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
         * @inheritdoc
         */
        protected function doMainQuery( $tables, $fields, $conds, $query_options,
-               $join_conds, FormOptions $opts ) {
-
+               $join_conds, FormOptions $opts
+       ) {
                $dbr = $this->getDB();
                $user = $this->getUser();
 
@@ -417,13 +422,14 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $fields[] = 'page_latest';
                $join_conds['page'] = [ 'LEFT JOIN', 'rc_cur_id=page_id' ];
 
+               $tagFilter = explode( '|', $opts['tagfilter'] );
                ChangeTags::modifyDisplayQuery(
                        $tables,
                        $fields,
                        $conds,
                        $join_conds,
                        $query_options,
-                       $opts['tagfilter']
+                       $tagFilter
                );
 
                if ( !$this->runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds,
@@ -436,13 +442,24 @@ class SpecialRecentChanges 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); prior to
                // MediaWiki 1.26 this used to use the plus operator instead, which meant
                // that extensions weren't able to change these conditions
-               $query_options = array_merge( [
-                       'ORDER BY' => 'rc_timestamp DESC',
-                       'LIMIT' => $opts['limit'] ], $query_options );
+               $query_options = array_merge( $orderByAndLimit, $query_options );
                $rows = $dbr->select(
                        $tables,
                        $fields,
@@ -521,6 +538,10 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
                $userShowHiddenCats = $this->getUser()->getBoolOption( 'showhiddencats' );
                $rclistOutput = $list->beginRecentChangesList();
+               if ( $this->isStructuredFilterUiEnabled() ) {
+                       $rclistOutput .= $this->makeLegend();
+               }
+
                foreach ( $rows as $obj ) {
                        if ( $limit == 0 ) {
                                break;
@@ -588,7 +609,9 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $nondefaults = $opts->getChangedValues();
 
                $panel = [];
-               $panel[] = $this->makeLegend();
+               if ( !$this->isStructuredFilterUiEnabled() ) {
+                       $panel[] = $this->makeLegend();
+               }
                $panel[] = $this->optionsPanel( $defaults, $nondefaults, $numRows );
                $panel[] = '<hr />';