Merge "RCFilters: Move parameter operations to ViewModel"
[lhc/web/wiklou.git] / includes / specialpage / ChangesListSpecialPage.php
index 6fd33a7..3f45250 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.
@@ -619,7 +692,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
 
                        $out->addJsConfigVars(
                                'wgRCFiltersChangeTags',
-                               $this->buildChangeTagList()
+                               $this->getChangeTagList()
                        );
                        $out->addJsConfigVars(
                                'StructuredChangeFiltersDisplayConfig',
@@ -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' );
                }
@@ -661,49 +724,60 @@ abstract class ChangesListSpecialPage extends SpecialPage {
         *
         * @return Array Tag data
         */
-       protected function buildChangeTagList() {
-               $explicitlyDefinedTags = array_fill_keys( ChangeTags::listExplicitlyDefinedTags(), 0 );
-               $softwareActivatedTags = array_fill_keys( ChangeTags::listSoftwareActivatedTags(), 0 );
-
-               // Hit counts disabled for perf reasons, see T169997
-               /*
-               $tagStats = ChangeTags::tagUsageStatistics();
-               $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags, $tagStats );
-
-               // Sort by hits
-               arsort( $tagHitCounts );
-               */
-               $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags );
-
-               // Build the list and data
-               $result = [];
-               foreach ( $tagHitCounts as $tagName => $hits ) {
-                       if (
-                               // Only get active tags
-                               isset( $explicitlyDefinedTags[ $tagName ] ) ||
-                               isset( $softwareActivatedTags[ $tagName ] )
-                       ) {
-                               // Parse description
-                               $desc = ChangeTags::tagLongDescriptionMessage( $tagName, $this->getContext() );
-
-                               $result[] = [
-                                       'name' => $tagName,
-                                       'label' => Sanitizer::stripAllTags(
-                                               ChangeTags::tagDescription( $tagName, $this->getContext() )
-                                       ),
-                                       'description' => $desc ? Sanitizer::stripAllTags( $desc->parse() ) : '',
-                                       'cssClass' => Sanitizer::escapeClass( 'mw-tag-' . $tagName ),
-                                       'hits' => $hits,
-                               ];
-                       }
-               }
+       protected function getChangeTagList() {
+               $cache = ObjectCache::getMainWANInstance();
+               $context = $this->getContext();
+               return $cache->getWithSetCallback(
+                       $cache->makeKey( 'changeslistspecialpage-changetags', $context->getLanguage()->getCode() ),
+                       $cache::TTL_MINUTE * 10,
+                       function () use ( $context ) {
+                               $explicitlyDefinedTags = array_fill_keys( ChangeTags::listExplicitlyDefinedTags(), 0 );
+                               $softwareActivatedTags = array_fill_keys( ChangeTags::listSoftwareActivatedTags(), 0 );
+
+                               // Hit counts disabled for perf reasons, see T169997
+                               /*
+                               $tagStats = ChangeTags::tagUsageStatistics();
+                               $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags, $tagStats );
+
+                               // Sort by hits
+                               arsort( $tagHitCounts );
+                               */
+                               $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags );
+
+                               // Build the list and data
+                               $result = [];
+                               foreach ( $tagHitCounts as $tagName => $hits ) {
+                                       if (
+                                               // Only get active tags
+                                               isset( $explicitlyDefinedTags[ $tagName ] ) ||
+                                               isset( $softwareActivatedTags[ $tagName ] )
+                                       ) {
+                                               // Parse description
+                                               $desc = ChangeTags::tagLongDescriptionMessage( $tagName, $context );
+
+                                               $result[] = [
+                                                       'name' => $tagName,
+                                                       'label' => Sanitizer::stripAllTags(
+                                                               ChangeTags::tagDescription( $tagName, $context )
+                                                       ),
+                                                       'description' => $desc ? Sanitizer::stripAllTags( $desc->parse() ) : '',
+                                                       'cssClass' => Sanitizer::escapeClass( 'mw-tag-' . $tagName ),
+                                                       'hits' => $hits,
+                                               ];
+                                       }
+                               }
 
-               // Instead of sorting by hit count (disabled, see above), sort by display name
-               usort( $result, function ( $a, $b ) {
-                       return strcasecmp( $a['label'], $b['label'] );
-               } );
+                               // Instead of sorting by hit count (disabled, see above), sort by display name
+                               usort( $result, function ( $a, $b ) {
+                                       return strcasecmp( $a['label'], $b['label'] );
+                               } );
 
-               return $result;
+                               return $result;
+                       },
+                       [
+                               'lockTSE' => 30
+                       ]
+               );
        }
 
        /**
@@ -1221,8 +1295,10 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                        // 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()] );
+                               if ( $filterGroup->isActive( $isStructuredUI ) ) {
+                                       $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 ) ) {
@@ -1456,8 +1532,10 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                        $context->msg( 'recentchanges-legend-heading' )->parse();
 
                # Collapsible
+               $collapsedState = $this->getRequest()->getCookie( 'changeslist-state' );
+               $collapsedClass = $collapsedState === 'collapsed' ? ' mw-collapsed' : '';
                $legend =
-                       '<div class="mw-changeslist-legend">' .
+                       '<div class="mw-changeslist-legend mw-collapsible' . $collapsedClass . '">' .
                                $legendHeading .
                                '<div class="mw-collapsible-content">' . $legend . '</div>' .
                        '</div>';