Merge "RCFilters: define consistent interface in ChangesListFilterGroup"
[lhc/web/wiklou.git] / includes / specialpage / ChangesListSpecialPage.php
index dcd14e8..67f68ea 100644 (file)
@@ -540,6 +540,8 @@ abstract class ChangesListSpecialPage extends SpecialPage {
        public function execute( $subpage ) {
                $this->rcSubpage = $subpage;
 
+               $this->considerActionsForDefaultSavedQuery();
+
                $rows = $this->getRows();
                $opts = $this->getOptions();
                if ( $rows === false ) {
@@ -591,6 +593,77 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                $this->includeRcFiltersApp();
        }
 
+       /**
+        * Check whether or not the page should load defaults, and if so, whether
+        * a default saved query is relevant to be redirected to. If it is relevant,
+        * redirect properly with all necessary query parameters.
+        */
+       protected function considerActionsForDefaultSavedQuery() {
+               if ( !$this->isStructuredFilterUiEnabled() ) {
+                       return;
+               }
+
+               $knownParams = call_user_func_array(
+                       [ $this->getRequest(), 'getValues' ],
+                       array_keys( $this->getOptions()->getAllValues() )
+               );
+
+               // HACK: Temporarily until we can properly define "sticky" filters and parameters,
+               // we need to exclude several parameters we know should not be counted towards preventing
+               // the loading of defaults.
+               $excludedParams = [ 'limit' => '', 'days' => '', 'enhanced' => '', 'from' => '' ];
+               $knownParams = array_diff_key( $knownParams, $excludedParams );
+
+               if (
+                       // If there are NO known parameters in the URL request
+                       // (that are not excluded) then we need to check into loading
+                       // the default saved query
+                       count( $knownParams ) === 0
+               ) {
+                       // Get the saved queries data and parse it
+                       $savedQueries = FormatJson::decode(
+                               $this->getUser()->getOption( static::$savedQueriesPreferenceName ),
+                               true
+                       );
+
+                       if ( $savedQueries && isset( $savedQueries[ 'default' ] ) ) {
+                               // Only load queries that are 'version' 2, since those
+                               // have parameter representation
+                               if ( isset( $savedQueries[ 'version' ] ) && $savedQueries[ 'version' ] === '2' ) {
+                                       $savedQueryDefaultID = $savedQueries[ 'default' ];
+                                       $defaultQuery = $savedQueries[ 'queries' ][ $savedQueryDefaultID ][ 'data' ];
+
+                                       // Build the entire parameter list
+                                       $query = array_merge(
+                                               $defaultQuery[ 'params' ],
+                                               $defaultQuery[ 'highlights' ],
+                                               [
+                                                       'urlversion' => '2',
+                                               ]
+                                       );
+                                       // Add to the query any parameters that we may have ignored before
+                                       // but are still valid and requested in the URL
+                                       $query = array_merge( $this->getRequest()->getValues(), $query );
+                                       unset( $query[ 'title' ] );
+                                       $this->getOutput()->redirect( $this->getPageTitle()->getCanonicalURL( $query ) );
+                               } else {
+                                       // There's a default, but the version is not 2, and the server can't
+                                       // actually recognize the query itself. This happens if it is before
+                                       // the conversion, so we need to tell the UI to reload saved query as
+                                       // it does the conversion to version 2
+                                       $this->getOutput()->addJsConfigVars(
+                                               'wgStructuredChangeFiltersDefaultSavedQueryExists',
+                                               true
+                                       );
+
+                                       // Add the class that tells the frontend it is still loading
+                                       // another query
+                                       $this->getOutput()->addBodyClasses( 'mw-rcfilters-ui-loading' );
+                               }
+                       }
+               }
+       }
+
        /**
         * Include the modules and configuration for the RCFilters app.
         * Conditional on the user having the feature enabled.
@@ -632,25 +705,15 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                                ]
                        );
 
+                       $out->addJsConfigVars(
+                               'wgStructuredChangeFiltersSavedQueriesPreferenceName',
+                               static::$savedQueriesPreferenceName
+                       );
+
                        $out->addJsConfigVars(
                                'StructuredChangeFiltersLiveUpdatePollingRate',
                                $this->getConfig()->get( 'StructuredChangeFiltersLiveUpdatePollingRate' )
                        );
-
-                       if ( static::$savedQueriesPreferenceName ) {
-                               $savedQueries = FormatJson::decode(
-                                       $this->getUser()->getOption( static::$savedQueriesPreferenceName )
-                               );
-                               if ( $savedQueries && isset( $savedQueries->default ) ) {
-                                       // If there is a default saved query, show a loading spinner,
-                                       // since the frontend is going to reload the results
-                                       $out->addBodyClasses( 'mw-rcfilters-ui-loading' );
-                               }
-                               $out->addJsConfigVars(
-                                       'wgStructuredChangeFiltersSavedQueriesPreferenceName',
-                                       static::$savedQueriesPreferenceName
-                               );
-                       }
                } else {
                        $out->addBodyClasses( 'mw-rcfilters-disabled' );
                }
@@ -907,6 +970,23 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                return $unstructuredGroupDefinition;
        }
 
+       /**
+        * @return array The legacy show/hide toggle filters
+        */
+       protected function getLegacyShowHideFilters() {
+               $filters = [];
+               foreach ( $this->filterGroups as $group ) {
+                       if ( $group instanceof  ChangesListBooleanFilterGroup ) {
+                               foreach ( $group->getFilters() as $key => $filter ) {
+                                       if ( $filter->displaysOnUnstructuredUi( $this ) ) {
+                                               $filters[ $key ] = $filter;
+                                       }
+                               }
+                       }
+               }
+               return $filters;
+       }
+
        /**
         * Register all the filters, including legacy hook-driven ones.
         * Then create a FormOptions object with options as specified by the user
@@ -947,19 +1027,9 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                // If urlversion=2 is set, ignore the filter defaults and set them all to false/empty
                $useDefaults = $this->getRequest()->getInt( 'urlversion' ) !== 2;
 
-               // Add all filters
                /** @var ChangesListFilterGroup $filterGroup */
                foreach ( $this->filterGroups as $filterGroup ) {
-                       // URL parameters can be per-group, like 'userExpLevel',
-                       // or per-filter, like 'hideminor'.
-                       if ( $filterGroup->isPerGroupRequestParameter() ) {
-                               $opts->add( $filterGroup->getName(), $useDefaults ? $filterGroup->getDefault() : '' );
-                       } else {
-                               /** @var ChangesListBooleanFilter $filter */
-                               foreach ( $filterGroup->getFilters() as $filter ) {
-                                       $opts->add( $filter->getName(), $useDefaults ? $filter->getDefault( $structuredUI ) : false );
-                               }
-                       }
+                       $filterGroup->addOptions( $opts, $useDefaults, $structuredUI );
                }
 
                $opts->add( 'namespace', '', FormOptions::STRING );
@@ -1090,9 +1160,9 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                // or per-filter, like 'hideminor'.
 
                foreach ( $this->filterGroups as $filterGroup ) {
-                       if ( $filterGroup->isPerGroupRequestParameter() ) {
+                       if ( $filterGroup instanceof ChangesListStringOptionsFilterGroup ) {
                                $stringParameterNameSet[$filterGroup->getName()] = true;
-                       } elseif ( $filterGroup->getType() === ChangesListBooleanFilterGroup::TYPE ) {
+                       } elseif ( $filterGroup instanceof ChangesListBooleanFilterGroup ) {
                                foreach ( $filterGroup->getFilters() as $filter ) {
                                        $hideParameterNameSet[$filter->getName()] = true;
                                }
@@ -1122,7 +1192,10 @@ abstract class ChangesListSpecialPage extends SpecialPage {
         * @param FormOptions $opts
         */
        public function validateOptions( FormOptions $opts ) {
-               if ( $this->fixContradictoryOptions( $opts ) ) {
+               $isContradictory = $this->fixContradictoryOptions( $opts );
+               $isReplaced = $this->replaceOldOptions( $opts );
+
+               if ( $isContradictory || $isReplaced ) {
                        $query = wfArrayToCgi( $this->convertParamsForLink( $opts->getChangedValues() ) );
                        $this->getOutput()->redirect( $this->getPageTitle()->getCanonicalURL( $query ) );
                }
@@ -1193,6 +1266,34 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                return false;
        }
 
+       /**
+        * Replace old options 'hideanons' or 'hideliu' with structured UI equivalent
+        *
+        * @param FormOptions $opts
+        * @return bool True if the change was made
+        */
+       public function replaceOldOptions( FormOptions $opts ) {
+               if ( !$this->isStructuredFilterUiEnabled() ) {
+                       return false;
+               }
+
+               // At this point 'hideanons' and 'hideliu' cannot be both true,
+               // because fixBackwardsCompatibilityOptions resets (at least) 'hideanons' in such case
+               if ( $opts[ 'hideanons' ] ) {
+                       $opts->reset( 'hideanons' );
+                       $opts[ 'userExpLevel' ] = 'registered';
+                       return true;
+               }
+
+               if ( $opts[ 'hideliu' ] ) {
+                       $opts->reset( 'hideliu' );
+                       $opts[ 'userExpLevel' ] = 'unregistered';
+                       return true;
+               }
+
+               return false;
+       }
+
        /**
         * Convert parameters values from true/false to 1/0
         * so they are not omitted by wfArrayToCgi()
@@ -1228,20 +1329,10 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                $dbr = $this->getDB();
                $isStructuredUI = $this->isStructuredFilterUiEnabled();
 
+               /** @var ChangesListFilterGroup $filterGroup */
                foreach ( $this->filterGroups as $filterGroup ) {
-                       // URL parameters can be per-group, like 'userExpLevel',
-                       // or per-filter, like 'hideminor'.
-                       if ( $filterGroup->isPerGroupRequestParameter() ) {
-                               $filterGroup->modifyQuery( $dbr, $this, $tables, $fields, $conds,
-                                       $query_options, $join_conds, $opts[$filterGroup->getName()] );
-                       } else {
-                               foreach ( $filterGroup->getFilters() as $filter ) {
-                                       if ( $filter->isActive( $opts, $isStructuredUI ) ) {
-                                               $filter->modifyQuery( $dbr, $this, $tables, $fields, $conds,
-                                                       $query_options, $join_conds );
-                                       }
-                               }
-                       }
+                       $filterGroup->modifyQuery( $dbr, $this, $tables, $fields, $conds,
+                               $query_options, $join_conds, $opts, $isStructuredUI );
                }
 
                // Namespace filtering